daemon.h - Daemon Process Utilities

The daemon process utilities are designed to make it easy to create a standard daemon process which interacts with signals and the standard shared memory segment. Processes that utilise these routines properly are also compatible with the watchdog utility that comes with the library.


Initialising your daemon

The first action a daemon would perform is to disconnect from its parent and controlling terminal and standard files.
    pid_t leavehome( void );
This function performs the following sequence of actions.
  1. Closes the current stdin, stdout & stderr files and re-opens them to configuration defined locations. This is done via a call to restart_files.
  2. performs a fork to disconnect from the parent.
  3. performs a setsid to disconnect from the process group.


restart_files

    int restart_files( void );

    int restart_these_files( const char *in_name,
			    const char *out_name,
			    const char *err_name );
This pair of functions performs an freopen on the standard I/O streams stdin, stdout & stderr.

The restart_files function gets the filenames for the streams by evaluating the configuration file parameters STDIN, STDOUT & STDERR. If the evaluations produce NULL or empty string then the default value of /dev/null is used.

The restart_these_files function behaves as above with the exception that the file names are explicitly provided. As with restart_files should any parameter be NULL or an empty string then the value /dev/null is used.


Signal Handling

Daemon processes normally arrange for various signals to be trapped. The following signall routines are provided as a basis.
    int init_signalling( void );
    int check_signalling( void );

    int allow_sysint( void );
    int deny_sysint( void );
The init_signalling routine sets up a standard handler for the following signals The signal handler copies the value of signal received into a local variable, and will usually re-start any system cal that was in progress at the time.

The check_signalling routine returns the value of any stored signal received. The value is also cleared.

The allow_sysint routine saves a copy of the signal handler state for the above listed signals and puts in place copies with the SA_RESTART flag cleared. This function only has effect once unless the deny_sysint function is called.

The deny_sysint routine takes the previously saved state of the signal handlers (saved via a call to allow_sysint) and restores them.


Waiting For An Event

    int mp_daemon_sleep( int how_long );
This function provides the facility to sleep for the supplied number of seconds, but also to be woken if an interrupt occurs, or if a process pipe exists when a character is received. It uses a select call along with allow_sysint & deny_sysint.


Simplifying The Main Loop

    int mp_daemon_loop( int(*poll_func)(int),
			int(*u1_func)(int),
			int(*u2_func)(int),
			int(*int_func)(int),
			int(*term_func)(int),
			int flags );
The sequence it performs each time round its loop is as follows;
  1. Get the current value of POLL_PERIOD from the configuration file.
  2. Call the check_signalling function.
    1. If the value is SIGHUP then the restart_files routine is called. The value 0 is passed to the next major step.
    2. If the value returned is one of SIGINT, SIGTERM, SIGUSR1 or SIGUSR2 and the corresponding function parameter is non-NULL then the function is called with the signal value as the sole parameter. The return value of the function is saved for the next major step.
    3. If the value is one of SIGINT, SIGTERM, but the corresponding function pointer is NULL then the value is passed to the next major step.
    4. If the value is one of SIGUSR1 or SIGUSR2 but the corresponding function pointer is NULL then 0 is passed to the next major step.
    5. If the value is zero or the signal is not one of the ones mentioned above the poll routine is called with 0 as its parameter and the return value saved for the next major step.
  3. If the result of the check_signalling stage is zero, then the mp_daemon_sleep routine is called with the value of the POLL_PERIOD.
  4. If the result is non-zero the routine exits.

The poll_func parameter must be a non-NULL pointer to a function taking an integer parameter, and returning an integer.

The next four parameters, u1_func, u2_func, int_func & term_func are similar function pointers but NULL may be supplied.

The flags parameter should be 0.

Note that because the functions are passed the value of the signal or 0 it is possible to use the same function for all of the parameters.