[Previous] [Contents] [Next]

procmgr_event_notify()

Notify us of system-wide events

Synopsis:

#include <sys/procmgr.h>

int procmgr_event_notify
            ( unsigned flags,
              const struct sigevent * event );

Library:

libc

Description:

The procmgr_event_notify() function requests that the process manager notify the caller of the system-wide events identified by the given flags. A process may have only one notificaton request active at a time. Setting flags to 0 (zero) unarms the event.

The event is described in the sigevent structure pointed to by event.

Flags

Flags currently defined in <sys/procmgr.h> are:

PROCMGR_EVENT_DAEMON_DEATH
Notify the caller when any process in session 1 dies. This is most useful for watching for the death of daemon processes which use procmgr_daemon() to put themselves in session 1 as well as close and redirect file descriptors. As a result of this closing and redirecting, the death of daemons are difficult to detect otherwise.

Note that notification will be via the given event so no information will be provided on which process died. Once you've received the event, you'll need to do something else to find out if processes you care about had died. This can be done by walking through the list of all processes looking for specific process ids or process names. If you don't find one then it has died. The sample code below demonstrates how this can be done.

PROCMGR_EVENT_SYNC
Notify the caller of any calls to sync() the filesystems.

Returns:

-1 on error; any other value indicates success.

Examples:

/*
 * This demonstrates procmgr_event_notify() with the 
 * PROCMGR_DAEMON_DEATH flag. This flag allows you to 
 * be notified if any process in session 1 dies.  
 * Daemons are processes that do things that make
 * their death hard to detect (they become daemons by calling
 * procmgr_daemon()).  One of the things that happens is that
 * daemons end up in session 1.  Hence, the usefulness of the
 * PROCMGR_DAEMON_DEATH flag.
 *
 * When you are notified, you're not told who died.
 * It's up to you to know who should be running.  Once notified,
 * you could then walk through the list of which processes are
 * still running and see if all the expected processes are still
 * running. If you know the process id of the processes you
 * are watching out for then this is easiest.  If you don't know
 * the process id then your next option may be by process name.
 * The code below does a lookup by process name.
 */

#include <devctl.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/neutrino.h>
#include <sys/procfs.h>
#include <sys/procmgr.h>

static int check_if_running( char *process );

#define DAEMON_DIED_CODE   (_PULSE_CODE_MINAVAIL)

struct dinfo_s {
    procfs_debuginfo    info;
    char                pathbuffer[PATH_MAX];
};

int
main( int argc, char **argv )
{
    char            *daemon_to_watch;
    int             chid, coid, rcvid;
    struct sigevent event;
    struct _pulse   msg;
    
    if (argc != 2) {
        printf( "use: %s process_to_watch_for\n", argv[0] );
        exit( EXIT_FAILURE );
    }
    
    daemon_to_watch = argv[1];   /* the process to watch for */
    
    chid = ChannelCreate( 0 );
    coid = ConnectAttach( 0, 0, chid, _NTO_SIDE_CHANNEL, 0 );
    SIGEV_PULSE_INIT( &event, coid, SIGEV_PULSE_PRIO_INHERIT,
                      DAEMON_DIED_CODE, 0 );

    /*
     * Ask to be notified via a pulse whenever a 
     * daemon process dies
     */
     
    if (procmgr_event_notify( PROCMGR_EVENT_DAEMON_DEATH, 
                              &event ) == -1) {
        fprintf( stderr, "procmgr_event_notify() failed" );
        exit( EXIT_FAILURE );
    }

    while (1) {
        rcvid = MsgReceive( chid, &msg, sizeof(msg), NULL );
        if (rcvid != 0) {
            /* not a pulse, could be unexpected message or error */
            exit( EXIT_FAILURE );
        }
        
        if (check_if_running( daemon_to_watch ) == 0)
            printf( "%s is no longer running\n", daemon_to_watch );
    }    
    return 0;
}

/*
 * check_if_running - This will walk through all processes 
 * to see if this particular one is still running.
 */
 
static int
check_if_running( char *process )
{
    DIR             *dirp;
    struct dirent   *dire;
    char            buffer[20];
    int             fd, status;
    pid_t           pid;
    struct dinfo_s  dinfo;
    
    if ((dirp = opendir( "/proc" )) == NULL) {
        perror( "Could not open '/proc'" );
        return -1;
    }
    while (1) {
        if ((dire = readdir( dirp )) == NULL)
            break;
        if (isdigit( dire->d_name[0] )) {
            pid = strtoul( dire->d_name, NULL, 0 );
    
            sprintf( buffer, "/proc/%d/as", pid );
            if ((fd = open( buffer, O_RDONLY )) != NULL) {
                status = devctl( fd, DCMD_PROC_MAPDEBUG_BASE,
                                 &dinfo, sizeof(dinfo), NULL );
                if (status == EOK) {
                    if (!strcmp( process, basename( dinfo.info.path ) ))
                        return 1;
                } /* else some errors are expected, e.g. procnto has 
                     no MAPDEBUG info and there is a timing issue 
                     with getting info on the process that died, 
                     ignore errors */
                close( fd );
            }
        }
    }
    closedir( dirp );
    return 0;
}

Classification:

QNX 6

Safety:
Cancellation point No
Interrupt handler No
Signal handler Yes
Thread Yes

See also:

procmgr_daemon(), procmgr_event_trigger()

sigevent structure


[Previous] [Contents] [Next]