Simple restart

The most basic form of recovery is the simple death-restart mechanism. Since the QNX Neutrino RTOS provides virtually all non-kernel functionality via user-installable programs, and since it offers complete memory protection, not only for user applications, but also for OS components (device drivers, filesystems, etc.), a resource manager or other server program can be easily decoupled from the OS.

This decoupling lets you safely stop, start, and upgrade resource managers or other key programs dynamically, without compromising the availability of the rest of the system.

Consider the following code, where we restart the inetd daemon:

/* addinet.c */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/netmgr.h>
#include <fcntl.h>
#include <ha/ham.h>

int main(int argc, char *argv[])
{
      int status;
      char *inetdpath;
    ham_entity_t *ehdl;
    ham_condition_t *chdl;
    ham_action_t *ahdl;
    int inetdpid;
    if (argc > 1)
        inetdpath = strdup(argv[1]);    
    else 
        inetdpath = strdup("/usr/sbin/inetd -D");
    if (argc > 2)
        inetdpid = atoi(argv[2]);
    else
        inetdpid = -1;
    ham_connect(0);
    ehdl = ham_attach("inetd", ND_LOCAL_NODE, inetdpid, inetdpath, 0);
    if (ehdl != NULL)
    {
      chdl = ham_condition(ehdl,CONDDEATH, "death", HREARMAFTERRESTART);
    if (chdl != NULL) {
        ahdl = ham_action_restart(chdl, "restart", inetdpath, 
                              HREARMAFTERRESTART);
          if (ahdl == NULL)    
              printf("add action failed\n");
        }
        else
            printf("add condition failed\n");
    }
    else
        printf("add entity failed\n");
    ham_disconnect(0);
    exit(0);
}

The above example attaches the inetd process to a HAM, and then establishes a condition death and an action restart under it.

Note: If inetd isn't a self-attached entity, you need to specify the -D option to it, to force inetd to daemonize by calling procmgr_daemon() instead of by calling daemon(). The HAM can see death messages only from self-attached entities, processes that terminate abnormally, and tasks that are running in session 1, and the call to daemon() doesn't put the caller into that session.

If inetd is a self-attached entity, you don't need to specify the -D option because the HAM automatically switches to monitoring the new process that daemon() creates.

When inetd terminates, the HAM will automatically restart it by running the program specified by inetdpath. If inetd were already running on the system, we can pass the pid of the existing inetd into inetdpid and it will be attached to directly. Otherwise, the HAM will start and begin to monitor inetd.

You could use the same code to monitor, say, slogger (by specifying /usr/sbin/slogger), mqueue (by specifying /sbin/mqueue), etc. Just remember to specify the full path of the executable with all its required command-line parameters.