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.
- Closes the current stdin, stdout & stderr
files and re-opens them to configuration defined locations. This is done
via a call to
restart_files.
- performs a fork to disconnect from the parent.
- performs a setsid to disconnect from the process group.
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
- SIGINT
- SIGTERM
- SIGUSR1
- SIGUSR2
- SIGHUP
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;
- Get the current value of
POLL_PERIOD
from the configuration file.
- Call the check_signalling function.
- If the value is SIGHUP then the
restart_files routine is called. The value 0
is passed to the next major step.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.