Caution: This version of this document is no longer maintained. For the latest documentation, see http://www.qnx.com/developers/docs.

procmgr_event_notify()

Ask to be notified of system-wide events

Synopsis:

#include <sys/procmgr.h>

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

Arguments:

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

Setting flags to 0 (zero) unarms the event.

event
A pointer to a sigevent structure that specifies how you want to notified.

Library:

libc

Use the -l c option to qcc to link against this library. This library is usually included automatically.

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 notification request active at a time.

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 an 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 ) ))
                    {
                        closedir (dirp);

                        /* You should close fd to prevent memory leaking */
                        close(fd); 
                       
                        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 Neutrino

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

See also:

procmgr_daemon(), procmgr_event_trigger(), _pulse, sigevent