diff -cr --exclude=man --exclude=html --exclude=README_FILES --new-file /var/tmp/postfix-2.10-20120305/HISTORY ./HISTORY
*** /var/tmp/postfix-2.10-20120305/HISTORY Mon Mar 5 10:35:50 2012
--- ./HISTORY Tue Mar 6 19:40:04 2012
***************
*** 17668,17670 ****
--- 17668,17685 ----
of specific permit-like actions in Postfix SMTP server
access lists. Files: mantools/postlink, proto/postconf.proto,
global/mail_params.h, smtpd/smtpd.c, smtpd/smtpd_check.c.
+
+ 20120206
+
+ Workaround: some Linux systems don't use "postfix status"
+ to find out if the mail system still runs. Instead they
+ claim that Postfix runs even when the master has aborted.
+ Even worse, they refuse to start Postfix when the problem
+ is fixed, claiming that Postfix is still running! As a
+ workaround, "postfix start" now waits until *after* master
+ daemon process initialization and returns a non-zero exit
+ status if daemon initialization did not complete in time.
+ Of course the real fix is that Linux systems stop reporting
+ bogus information and use "postfix status" properly. Files:
+ conf/postfix-script, master/master.c, master/master.h.
+ master/master_monitor.c.
diff -cr --exclude=man --exclude=html --exclude=README_FILES --new-file /var/tmp/postfix-2.10-20120305/conf/postfix-script ./conf/postfix-script
*** /var/tmp/postfix-2.10-20120305/conf/postfix-script Fri Jan 15 20:07:52 2010
--- ./conf/postfix-script Wed Mar 7 13:01:37 2012
***************
*** 124,130 ****
$daemon_directory/postfix-script check-warn
fi
$INFO starting the Postfix mail system
! $daemon_directory/master &
;;
drain)
--- 124,134 ----
$daemon_directory/postfix-script check-warn
fi
$INFO starting the Postfix mail system
! # NOTE: wait in foreground process to get the initialization status.
! $daemon_directory/master -w || {
! $FATAL "mail system startup failed"
! exit 1
! }
;;
drain)
diff -cr --exclude=man --exclude=html --exclude=README_FILES --new-file /var/tmp/postfix-2.10-20120305/src/master/Makefile.in ./src/master/Makefile.in
*** /var/tmp/postfix-2.10-20120305/src/master/Makefile.in Sun Jan 22 10:55:16 2012
--- ./src/master/Makefile.in Wed Mar 7 11:37:49 2012
***************
*** 2,11 ****
SRCS = master.c master_conf.c master_ent.c master_sig.c master_avail.c \
master_spawn.c master_service.c master_status.c master_listen.c \
master_proto.c single_server.c multi_server.c master_vars.c \
! master_wakeup.c master_flow.c master_watch.c mail_flow.c
OBJS = master.o master_conf.o master_ent.o master_sig.o master_avail.o \
master_spawn.o master_service.o master_status.o master_listen.o \
! master_vars.o master_wakeup.o master_watch.o master_flow.o
LIB_OBJ = single_server.o multi_server.o trigger_server.o master_proto.o \
mail_flow.o event_server.o
HDRS = mail_server.h master_proto.h mail_flow.h
--- 2,13 ----
SRCS = master.c master_conf.c master_ent.c master_sig.c master_avail.c \
master_spawn.c master_service.c master_status.c master_listen.c \
master_proto.c single_server.c multi_server.c master_vars.c \
! master_wakeup.c master_flow.c master_watch.c mail_flow.c \
! master_monitor.c
OBJS = master.o master_conf.o master_ent.o master_sig.o master_avail.o \
master_spawn.o master_service.o master_status.o master_listen.o \
! master_vars.o master_wakeup.o master_watch.o master_flow.o \
! master_monitor.o
LIB_OBJ = single_server.o multi_server.o trigger_server.o master_proto.o \
mail_flow.o event_server.o
HDRS = mail_server.h master_proto.h mail_flow.h
***************
*** 207,212 ****
--- 209,219 ----
master_listen.o: ../../include/vstring.h
master_listen.o: master.h
master_listen.o: master_listen.c
+ master_monitor.o: ../../include/iostuff.h
+ master_monitor.o: ../../include/msg.h
+ master_monitor.o: ../../include/sys_defs.h
+ master_monitor.o: master.h
+ master_monitor.o: master_monitor.c
master_proto.o: ../../include/msg.h
master_proto.o: ../../include/sys_defs.h
master_proto.o: master_proto.c
diff -cr --exclude=man --exclude=html --exclude=README_FILES --new-file /var/tmp/postfix-2.10-20120305/src/master/master.c ./src/master/master.c
*** /var/tmp/postfix-2.10-20120305/src/master/master.c Fri Dec 9 20:10:00 2011
--- ./src/master/master.c Wed Mar 7 13:24:14 2012
***************
*** 4,10 ****
/* SUMMARY
/* Postfix master process
/* SYNOPSIS
! /* \fBmaster\fR [\fB-Ddtv\fR] [\fB-c \fIconfig_dir\fR] [\fB-e \fIexit_time\fR]
/* DESCRIPTION
/* The \fBmaster\fR(8) daemon is the resident process that runs Postfix
/* daemons on demand: daemons to send or receive messages via the
--- 4,10 ----
/* SUMMARY
/* Postfix master process
/* SYNOPSIS
! /* \fBmaster\fR [\fB-Ddtvw\fR] [\fB-c \fIconfig_dir\fR] [\fB-e \fIexit_time\fR]
/* DESCRIPTION
/* The \fBmaster\fR(8) daemon is the resident process that runs Postfix
/* daemons on demand: daemons to send or receive messages via the
***************
*** 45,50 ****
--- 45,57 ----
/* Enable verbose logging for debugging purposes. This option
/* is passed on to child processes. Multiple \fB-v\fR options
/* make the software increasingly verbose.
+ /* .IP \fB-w\fR
+ /* Wait in a dummy foreground process, while the real master
+ /* daemon initializes in a background process. The dummy
+ /* foreground process returns a zero exit status only when the
+ /* master daemon initialization is successful.
+ /* .sp
+ /* This feature is available in Postfix 2.10 and later.
/* .PP
/* Signals:
/* .IP \fBSIGHUP\fR
***************
*** 63,69 ****
/* terminate only the master ("\fBpostfix stop\fR") and allow running
/* processes to finish what they are doing.
/* DIAGNOSTICS
! /* Problems are reported to \fBsyslogd\fR(8).
/* ENVIRONMENT
/* .ad
/* .fi
--- 70,78 ----
/* terminate only the master ("\fBpostfix stop\fR") and allow running
/* processes to finish what they are doing.
/* DIAGNOSTICS
! /* Problems are reported to \fBsyslogd\fR(8). The exit status
! /* is non-zero in case of problems, including problems while
! /* initializing as a master daemon process in the background.
/* ENVIRONMENT
/* .ad
/* .fi
***************
*** 221,227 ****
static NORETURN usage(const char *me)
{
! msg_fatal("usage: %s [-c config_dir] [-D (debug)] [-d (don't detach from terminal)] [-e exit_time] [-t (test)] [-v]", me);
}
MAIL_VERSION_STAMP_DECLARE;
--- 230,236 ----
static NORETURN usage(const char *me)
{
! msg_fatal("usage: %s [-c config_dir] [-D (debug)] [-d (don't detach from terminal)] [-e exit_time] [-t (test)] [-v] [-w (wait for initialization)]", me);
}
MAIL_VERSION_STAMP_DECLARE;
***************
*** 243,248 ****
--- 252,259 ----
VSTRING *why;
WATCHDOG *watchdog;
ARGV *import_env;
+ int wait_flag = 0;
+ int monitor_fd = -1;
/*
* Fingerprint executables and core dumps.
***************
*** 311,317 ****
/*
* Process JCL.
*/
! while ((ch = GETOPT(argc, argv, "c:Dde:tv")) > 0) {
switch (ch) {
case 'c':
if (setenv(CONF_ENV_PATH, optarg, 1) < 0)
--- 322,328 ----
/*
* Process JCL.
*/
! while ((ch = GETOPT(argc, argv, "c:Dde:tvw")) > 0) {
switch (ch) {
case 'c':
if (setenv(CONF_ENV_PATH, optarg, 1) < 0)
***************
*** 332,337 ****
--- 343,351 ----
case 'v':
msg_verbose++;
break;
+ case 'w':
+ wait_flag = 1;
+ break;
default:
usage(argv[0]);
/* NOTREACHED */
***************
*** 345,350 ****
--- 359,375 ----
usage(argv[0]);
/*
+ * Run a foreground monitor process that returns an exit status of 0 when
+ * the child background process reports successful initialization as a
+ * daemon process. We use a generous limit in case main/master.cf specify
+ * symbolic hosts/ports and the naming service is slow.
+ */
+ #define MASTER_INIT_TIMEOUT 100 /* keep this limit generous */
+
+ if (wait_flag)
+ monitor_fd = master_monitor(MASTER_INIT_TIMEOUT);
+
+ /*
* If started from a terminal, get rid of any tty association. This also
* means that all errors and warnings must go to the syslog daemon.
*/
***************
*** 471,476 ****
--- 496,509 ----
var_mail_version, var_config_dir);
/*
+ * Report successful initialization to the foreground monitor process.
+ */
+ if (monitor_fd >= 0) {
+ write(monitor_fd, "", 1);
+ (void) close(monitor_fd);
+ }
+
+ /*
* Process events. The event handler will execute the read/write/timer
* action routines. Whenever something has happened, see if we received
* any signal in the mean time. Although the master process appears to do
diff -cr --exclude=man --exclude=html --exclude=README_FILES --new-file /var/tmp/postfix-2.10-20120305/src/master/master.h ./src/master/master.h
*** /var/tmp/postfix-2.10-20120305/src/master/master.h Wed Sep 7 13:18:25 2011
--- ./src/master/master.h Tue Mar 6 17:06:35 2012
***************
*** 219,224 ****
--- 219,229 ----
extern void master_str_watch(const MASTER_STR_WATCH *);
extern void master_int_watch(MASTER_INT_WATCH *);
+ /*
+ * master_monitor.c
+ */
+ extern int master_monitor(int);
+
/* DIAGNOSTICS
/* BUGS
/* SEE ALSO
diff -cr --exclude=man --exclude=html --exclude=README_FILES --new-file /var/tmp/postfix-2.10-20120305/src/master/master_monitor.c ./src/master/master_monitor.c
*** /var/tmp/postfix-2.10-20120305/src/master/master_monitor.c Wed Dec 31 19:00:00 1969
--- ./src/master/master_monitor.c Tue Mar 6 17:32:19 2012
***************
*** 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
+ #include
+ #include
+ #include
+
+ /* Utility library. */
+
+ #include
+ #include
+
+ /* Application-specific. */
+
+ #include
+
+ /* 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, (char *) 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);
+ }
+ }
+ }