Detecting the termination of daemons or of all processes

Updated: October 26, 2022

What would happen if you've created some processes that subsequently made themselves daemons (i.e., called procmgr_daemon())? As we mentioned above, the wait*() functions and sigwaitinfo() won't help.

For these you can give the kernel an event, such as one containing a pulse, and have the kernel deliver that pulse to you whenever a daemon terminates. This request for notification is done by calling procmgr_event_notify() or procmgr_event_notify_add() with PROCMGR_EVENT_DAEMON_DEATH in flags.

The difference between these functions is that with procmgr_event_notify(), your process can have one notification request; if you call the function again, the request replaces the previous one. With procmgr_event_notify_add(), your process can have more than one notification request.

See the documentation for procmgr_event_notify() for an example that uses PROCMGR_EVENT_DAEMON_DEATH.

(QNX Neutrino 7.0 or later) The PROCMGR_EVENT_PROCESS_DEATH event type is similar to PROCMGR_EVENT_DAEMON_DEATH, but it requests notification of the death of all processes. If you set the SIGEV_FLAG_UPDATEABLE flag in the event, the notification includes the process ID of the process that died. Here's an example:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/neutrino.h>
#include <process.h>
#include <sys/procmgr.h>


int main(void)
{
   int chid, coid;
   int rcvid;
   struct _pulse pulse;
   struct sigevent ev;

   // Create a channel that's private to this process.
   // No other process can connect to it.
   chid = ChannelCreate( _NTO_CHF_PRIVATE );
   if (-1 == chid)
   {
      // Was there an error creating the channel?
      perror("ChannelCreate()"); // Look up the errno code and print
      exit(EXIT_FAILURE);
   }

   // To ask for pulse delivery, we need a connection to our own channel.
   coid = ConnectAttach( 0, 0, chid, _NTO_SIDE_CHANNEL, 0 );
   if (-1 == coid)
   {
      // Was there an error creating the channel?
      perror("ConnectAttach()"); // Look up the errno code and print
      exit(EXIT_FAILURE);
   }   

   SIGEV_PULSE_INIT( &ev, coid, 10, 1, 0 );
   SIGEV_MAKE_UPDATEABLE(&ev);

   // Request process death notifications
   procmgr_event_notify( PROCMGR_EVENT_PROCESS_DEATH, &ev );

   while (1)
   {
      rcvid = MsgReceive( chid, &pulse, sizeof pulse, NULL );
      if (-1 == rcvid)
      {
         // Was there an error receiving msg?
         perror("MsgReceive"); // Look up errno code and print
         exit(EXIT_FAILURE); // Give up
      }

      if( pulse.code == 1 )
      {
         printf("Process with pid %d died.\n", pulse.value.sival_int );
      }
      else
      {
         printf("Unexpected pulse, code: %d\n", pulse.code );
      }
   }
   return 0;
}