Ask to be notified of system-wide events
#include <sys/procmgr.h> int procmgr_event_notify ( unsigned flags, const struct sigevent * event );
For more information, see "Event types," below.
libc
Use the -l c option to qcc to link against this library. This library is usually included automatically.
The procmgr_event_notify() function requests that the process manager notify the caller of the system-wide events identified by the given flags.
To remove the current notification request, pass a value of 0 for flags.
The following event types are defined in <sys/procmgr.h>:
-1 on error; any other value indicates success.
/* * 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; }
Safety: | |
---|---|
Cancellation point | No |
Interrupt handler | No |
Signal handler | Yes |
Thread | Yes |