summaryrefslogtreecommitdiffstats
path: root/src/master/master_monitor.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/master/master_monitor.c')
-rw-r--r--src/master/master_monitor.c100
1 files changed, 100 insertions, 0 deletions
diff --git a/src/master/master_monitor.c b/src/master/master_monitor.c
new file mode 100644
index 0000000..403d07e
--- /dev/null
+++ b/src/master/master_monitor.c
@@ -0,0 +1,100 @@
+/*++
+/* 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
+/*--*/
+
+/* 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:
+ /* 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");
+ case 1:
+ /* The child process initialized successfully. */
+ exit(0);
+ }
+ }
+}