diff options
Diffstat (limited to 'src/master/master_monitor.c')
-rw-r--r-- | src/master/master_monitor.c | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/src/master/master_monitor.c b/src/master/master_monitor.c new file mode 100644 index 0000000..6b2ca65 --- /dev/null +++ b/src/master/master_monitor.c @@ -0,0 +1,106 @@ +/*++ +/* NAME +/* master_monitor 3 +/* SUMMARY +/* Postfix master - start-up monitoring +/* SYNOPSIS +/* #include "master.h" +/* +/* int master_monitor(time_limit) +/* int time_limit; +/* DESCRIPTION +/* master_monitor() forks off a background child process, and +/* returns in the child. The result value is the file descriptor +/* on which the child process must write one byte after it +/* completes successful initialization as a daemon process. +/* +/* The foreground process waits for the child's completion for +/* a limited amount of time. It terminates with exit status 0 +/* in case of success, non-zero otherwise. +/* DIAGNOSTICS +/* Fatal errors: system call failure. +/* BUGS +/* SEE ALSO +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/* +/* Wietse Venema +/* Google, Inc. +/* 111 8th Avenue +/* New York, NY 10011, USA +/*--*/ + +/* System library. */ + +#include <sys_defs.h> +#include <signal.h> +#include <unistd.h> +#include <stdlib.h> + +/* Utility library. */ + +#include <msg.h> +#include <iostuff.h> + +/* Application-specific. */ + +#include <master.h> + +/* master_monitor - fork off a foreground monitor process */ + +int master_monitor(int time_limit) +{ + pid_t pid; + int pipes[2]; + char buf[1]; + + /* + * Sanity check. + */ + if (time_limit <= 0) + msg_panic("master_monitor: bad time limit: %d", time_limit); + + /* + * Set up the plumbing for child-to-parent communication. + */ + if (pipe(pipes) < 0) + msg_fatal("pipe: %m"); + close_on_exec(pipes[0], CLOSE_ON_EXEC); + close_on_exec(pipes[1], CLOSE_ON_EXEC); + + /* + * Fork the child, and wait for it to report successful initialization. + */ + switch (pid = fork()) { + case -1: + /* Error. */ + msg_fatal("fork: %m"); + case 0: + /* Child. Initialize as daemon in the background. */ + close(pipes[0]); + return (pipes[1]); + default: + /* Parent. Monitor the child in the foreground. */ + close(pipes[1]); + switch (timed_read(pipes[0], buf, 1, time_limit, (void *) 0)) { + default: + msg_warn("%m while waiting for daemon initialization"); + /* The child process still runs, but something is wrong. */ + (void) kill(pid, SIGKILL); + /* FALLTHROUGH */ + case 0: + /* The child process exited prematurely. */ + msg_fatal("daemon initialization failure -- see logs for details"); + case 1: + /* The child process initialized successfully. */ + exit(0); + } + } +} |