Previously, all processes would shutdown on receiving SIGINT or SIGTERM. When going down, the parent process would kill all the other process and waitpid() them.
Now, only the parent process handles SIGTERM and SIGINT, other processes ignore them. Upon receiving one of these signals, the parent process all imsg sockets and waitpid() for the children. It fatal()s if one of the imsg sockets is closed unexpectedly. Other processes exit() "normally" when one of their imsg socket is closed (except for client connection on the control socket of course). That's how they are supposed to stop now. When doing so, they log as "debug" instead of "info" because useless logs are useless. This makes the shutdown sequence much saner. Eric. Index: ca.c =================================================================== RCS file: /cvs/src/usr.sbin/smtpd/ca.c,v retrieving revision 1.24 diff -u -p -r1.24 ca.c --- ca.c 4 Sep 2016 16:10:31 -0000 1.24 +++ ca.c 6 Sep 2016 19:33:45 -0000 @@ -66,29 +66,14 @@ static uint64_t rsae_reqid = 0; static void ca_shutdown(void) { - log_info("info: ca agent exiting"); + log_debug("debug: ca agent exiting"); _exit(0); } -static void -ca_sig_handler(int sig, short event, void *p) -{ - switch (sig) { - case SIGINT: - case SIGTERM: - ca_shutdown(); - break; - default: - fatalx("ca_sig_handler: unexpected signal"); - } -} - int ca(void) { struct passwd *pw; - struct event ev_sigint; - struct event ev_sigterm; purge_config(PURGE_LISTENERS|PURGE_TABLES|PURGE_RULES); @@ -110,10 +95,8 @@ ca(void) imsg_callback = ca_imsg; event_init(); - signal_set(&ev_sigint, SIGINT, ca_sig_handler, NULL); - signal_set(&ev_sigterm, SIGTERM, ca_sig_handler, NULL); - signal_add(&ev_sigint, NULL); - signal_add(&ev_sigterm, NULL); + signal(SIGINT, SIG_IGN); + signal(SIGTERM, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGHUP, SIG_IGN); @@ -242,6 +225,9 @@ ca_imsg(struct mproc *p, struct imsg *im int ret = 0; uint64_t id; int v; + + if (imsg == NULL) + ca_shutdown(); if (p->proc == PROC_PARENT) { switch (imsg->hdr.type) { Index: control.c =================================================================== RCS file: /cvs/src/usr.sbin/smtpd/control.c,v retrieving revision 1.116 diff -u -p -r1.116 control.c --- control.c 4 Sep 2016 16:10:31 -0000 1.116 +++ control.c 6 Sep 2016 19:33:45 -0000 @@ -63,7 +63,6 @@ static void control_shutdown(void); static void control_listen(void); static void control_accept(int, short, void *); static void control_close(struct ctl_conn *); -static void control_sig_handler(int, short, void *); static void control_dispatch_ext(struct mproc *, struct imsg *); static void control_digest_update(const char *, size_t, int); static void control_broadcast_verbose(int, int); @@ -89,6 +88,12 @@ control_imsg(struct mproc *p, struct ims const void *data; size_t sz; + if (imsg == NULL) { + if (p->proc != PROC_CLIENT) + control_shutdown(); + return; + } + if (p->proc == PROC_PONY) { switch (imsg->hdr.type) { case IMSG_CTL_SMTP_SESSION: @@ -186,19 +191,6 @@ control_imsg(struct mproc *p, struct ims imsg_to_str(imsg->hdr.type)); } -static void -control_sig_handler(int sig, short event, void *p) -{ - switch (sig) { - case SIGINT: - case SIGTERM: - control_shutdown(); - break; - default: - fatalx("control_sig_handler: unexpected signal"); - } -} - int control_create_socket(void) { @@ -245,8 +237,6 @@ int control(void) { struct passwd *pw; - struct event ev_sigint; - struct event ev_sigterm; purge_config(PURGE_EVERYTHING); @@ -271,10 +261,8 @@ control(void) imsg_callback = control_imsg; event_init(); - signal_set(&ev_sigint, SIGINT, control_sig_handler, NULL); - signal_set(&ev_sigterm, SIGTERM, control_sig_handler, NULL); - signal_add(&ev_sigint, NULL); - signal_add(&ev_sigterm, NULL); + signal(SIGINT, SIG_IGN); + signal(SIGTERM, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGHUP, SIG_IGN); @@ -305,7 +293,7 @@ control(void) static void control_shutdown(void) { - log_info("info: control process exiting"); + log_debug("debug: control agent exiting"); _exit(0); } Index: lka.c =================================================================== RCS file: /cvs/src/usr.sbin/smtpd/lka.c,v retrieving revision 1.196 diff -u -p -r1.196 lka.c --- lka.c 4 Sep 2016 16:10:31 -0000 1.196 +++ lka.c 6 Sep 2016 19:33:46 -0000 @@ -83,6 +83,9 @@ lka_imsg(struct mproc *p, struct imsg *i uint64_t reqid; int v; + if (imsg == NULL) + lka_shutdown(); + if (imsg->hdr.type == IMSG_MTA_DNS_HOST || imsg->hdr.type == IMSG_MTA_DNS_PTR || imsg->hdr.type == IMSG_SMTP_DNS_PTR || @@ -383,10 +386,6 @@ lka_sig_handler(int sig, short event, vo pid_t pid; switch (sig) { - case SIGINT: - case SIGTERM: - lka_shutdown(); - break; case SIGCHLD: do { pid = waitpid(-1, &status, WNOHANG); @@ -400,7 +399,7 @@ lka_sig_handler(int sig, short event, vo void lka_shutdown(void) { - log_info("info: lookup agent exiting"); + log_debug("debug: lookup agent exiting"); _exit(0); } @@ -408,8 +407,6 @@ int lka(void) { struct passwd *pw; - struct event ev_sigint; - struct event ev_sigterm; struct event ev_sigchld; purge_config(PURGE_LISTENERS); @@ -427,12 +424,10 @@ lka(void) imsg_callback = lka_imsg; event_init(); - signal_set(&ev_sigint, SIGINT, lka_sig_handler, NULL); - signal_set(&ev_sigterm, SIGTERM, lka_sig_handler, NULL); signal_set(&ev_sigchld, SIGCHLD, lka_sig_handler, NULL); - signal_add(&ev_sigint, NULL); - signal_add(&ev_sigterm, NULL); signal_add(&ev_sigchld, NULL); + signal(SIGINT, SIG_IGN); + signal(SIGTERM, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGHUP, SIG_IGN); Index: mproc.c =================================================================== RCS file: /cvs/src/usr.sbin/smtpd/mproc.c,v retrieving revision 1.26 diff -u -p -r1.26 mproc.c --- mproc.c 3 Sep 2016 16:06:26 -0000 1.26 +++ mproc.c 6 Sep 2016 19:33:46 -0000 @@ -88,6 +88,8 @@ mproc_init(struct mproc *p, int fd) void mproc_clear(struct mproc *p) { + log_debug("debug: clearing p=%s, fd=%d, pid=%d", p->name, p->imsgbuf.fd, p->pid); + event_del(&p->ev); close(p->imsgbuf.fd); imsg_clear(&p->imsgbuf); @@ -166,10 +168,8 @@ mproc_dispatch(int fd, short event, void /* NOTREACHED */ case 0: /* this pipe is dead, so remove the event handler */ - if (smtpd_process != PROC_CONTROL || - p->proc != PROC_CLIENT) - log_warnx("warn: %s -> %s: pipe closed", - proc_name(smtpd_process), p->name); + log_debug("debug: %s -> %s: pipe closed", + proc_name(smtpd_process), p->name); p->handler(p, NULL); return; default: @@ -181,10 +181,8 @@ mproc_dispatch(int fd, short event, void n = msgbuf_write(&p->imsgbuf.w); if (n == 0 || (n == -1 && errno != EAGAIN)) { /* this pipe is dead, so remove the event handler */ - if (smtpd_process != PROC_CONTROL || - p->proc != PROC_CLIENT) - log_warnx("warn: %s -> %s: pipe closed", - proc_name(smtpd_process), p->name); + log_debug("debug: %s -> %s: pipe closed", + proc_name(smtpd_process), p->name); p->handler(p, NULL); return; } Index: pony.c =================================================================== RCS file: /cvs/src/usr.sbin/smtpd/pony.c,v retrieving revision 1.15 diff -u -p -r1.15 pony.c --- pony.c 4 Sep 2016 16:10:31 -0000 1.15 +++ pony.c 6 Sep 2016 19:33:46 -0000 @@ -46,7 +46,6 @@ void mta_imsg(struct mproc *, struct ims void smtp_imsg(struct mproc *, struct imsg *); static void pony_shutdown(void); -static void pony_sig_handler(int, short, void *); void pony_imsg(struct mproc *p, struct imsg *imsg) @@ -54,6 +53,9 @@ pony_imsg(struct mproc *p, struct imsg * struct msg m; int v; + if (imsg == NULL) + pony_shutdown(); + switch (imsg->hdr.type) { case IMSG_CONF_START: return; @@ -132,22 +134,9 @@ pony_imsg(struct mproc *p, struct imsg * } static void -pony_sig_handler(int sig, short event, void *p) -{ - switch (sig) { - case SIGINT: - case SIGTERM: - pony_shutdown(); - break; - default: - fatalx("pony_sig_handler: unexpected signal"); - } -} - -static void pony_shutdown(void) { - log_info("info: pony agent exiting"); + log_debug("debug: pony agent exiting"); _exit(0); } @@ -155,8 +144,6 @@ int pony(void) { struct passwd *pw; - struct event ev_sigint; - struct event ev_sigterm; mda_postfork(); mta_postfork(); @@ -191,10 +178,8 @@ pony(void) mta_postprivdrop(); smtp_postprivdrop(); - signal_set(&ev_sigint, SIGINT, pony_sig_handler, NULL); - signal_set(&ev_sigterm, SIGTERM, pony_sig_handler, NULL); - signal_add(&ev_sigint, NULL); - signal_add(&ev_sigterm, NULL); + signal(SIGINT, SIG_IGN); + signal(SIGTERM, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGHUP, SIG_IGN); Index: queue.c =================================================================== RCS file: /cvs/src/usr.sbin/smtpd/queue.c,v retrieving revision 1.181 diff -u -p -r1.181 queue.c --- queue.c 4 Sep 2016 16:10:31 -0000 1.181 +++ queue.c 6 Sep 2016 19:33:47 -0000 @@ -45,7 +45,6 @@ static void queue_imsg(struct mproc *, s static void queue_timeout(int, short, void *); static void queue_bounce(struct envelope *, struct delivery_bounce *); static void queue_shutdown(void); -static void queue_sig_handler(int, short, void *); static void queue_log(const struct envelope *, const char *, const char *); static void queue_msgid_walk(int, short, void *); @@ -66,6 +65,9 @@ queue_imsg(struct mproc *p, struct imsg size_t n_evp; int fd, mta_ext, ret, v, flags, code; + if (imsg == NULL) + queue_shutdown(); + memset(&bounce, 0, sizeof(struct delivery_bounce)); if (p->proc == PROC_PONY) { @@ -636,22 +638,9 @@ queue_bounce(struct envelope *e, struct } static void -queue_sig_handler(int sig, short event, void *p) -{ - switch (sig) { - case SIGINT: - case SIGTERM: - queue_shutdown(); - break; - default: - fatalx("queue_sig_handler: unexpected signal"); - } -} - -static void queue_shutdown(void) { - log_info("info: queue handler exiting"); + log_debug("debug: queue agent exiting"); queue_close(); _exit(0); } @@ -662,8 +651,6 @@ queue(void) struct passwd *pw; struct timeval tv; struct event ev_qload; - struct event ev_sigint; - struct event ev_sigterm; purge_config(PURGE_EVERYTHING); @@ -698,10 +685,8 @@ queue(void) imsg_callback = queue_imsg; event_init(); - signal_set(&ev_sigint, SIGINT, queue_sig_handler, NULL); - signal_set(&ev_sigterm, SIGTERM, queue_sig_handler, NULL); - signal_add(&ev_sigint, NULL); - signal_add(&ev_sigterm, NULL); + signal(SIGINT, SIG_IGN); + signal(SIGTERM, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGHUP, SIG_IGN); Index: scheduler.c =================================================================== RCS file: /cvs/src/usr.sbin/smtpd/scheduler.c,v retrieving revision 1.54 diff -u -p -r1.54 scheduler.c --- scheduler.c 4 Sep 2016 16:10:31 -0000 1.54 +++ scheduler.c 6 Sep 2016 19:33:47 -0000 @@ -47,7 +47,6 @@ static void scheduler_imsg(struct mproc *, struct imsg *); static void scheduler_shutdown(void); -static void scheduler_sig_handler(int, short, void *); static void scheduler_reset_events(void); static void scheduler_timeout(int, short, void *); @@ -75,6 +74,9 @@ scheduler_imsg(struct mproc *p, struct i time_t timestamp; int v, r, type; + if (imsg == NULL) + scheduler_shutdown(); + switch (imsg->hdr.type) { case IMSG_QUEUE_ENVELOPE_SUBMIT: @@ -404,22 +406,9 @@ scheduler_imsg(struct mproc *p, struct i } static void -scheduler_sig_handler(int sig, short event, void *p) -{ - switch (sig) { - case SIGINT: - case SIGTERM: - scheduler_shutdown(); - break; - default: - fatalx("scheduler_sig_handler: unexpected signal"); - } -} - -static void scheduler_shutdown(void) { - log_info("info: scheduler handler exiting"); + log_debug("debug: scheduler agent exiting"); _exit(0); } @@ -438,8 +427,6 @@ int scheduler(void) { struct passwd *pw; - struct event ev_sigint; - struct event ev_sigterm; backend = scheduler_backend_lookup(backend_scheduler); if (backend == NULL) @@ -473,10 +460,8 @@ scheduler(void) imsg_callback = scheduler_imsg; event_init(); - signal_set(&ev_sigint, SIGINT, scheduler_sig_handler, NULL); - signal_set(&ev_sigterm, SIGTERM, scheduler_sig_handler, NULL); - signal_add(&ev_sigint, NULL); - signal_add(&ev_sigterm, NULL); + signal(SIGINT, SIG_IGN); + signal(SIGTERM, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGHUP, SIG_IGN); Index: smtpd.c =================================================================== RCS file: /cvs/src/usr.sbin/smtpd/smtpd.c,v retrieving revision 1.285 diff -u -p -r1.285 smtpd.c --- smtpd.c 6 Sep 2016 16:34:29 -0000 1.285 +++ smtpd.c 6 Sep 2016 19:33:48 -0000 @@ -60,7 +60,7 @@ static void parent_imsg(struct mproc *, struct imsg *); static void usage(void); static int smtpd(void); -static void parent_shutdown(int); +static void parent_shutdown(void); static void parent_send_config(int, short, void *); static void parent_send_config_lka(void); static void parent_send_config_pony(void); @@ -162,8 +162,8 @@ parent_imsg(struct mproc *p, struct imsg int fd, n, v, ret; if (imsg == NULL) - exit(1); - + fatalx("process %s socket closed", p->name); + if (p->proc == PROC_LKA) { switch (imsg->hdr.type) { case IMSG_LKA_OPEN_FORWARD: @@ -275,16 +275,16 @@ usage(void) } static void -parent_shutdown(int ret) +parent_shutdown(void) { - void *iter; - struct child *child; - pid_t pid; + pid_t pid; - iter = NULL; - while (tree_iter(&children, &iter, NULL, (void**)&child)) - if (child->type == CHILD_DAEMON) - kill(child->pid, SIGTERM); + mproc_clear(p_ca); + mproc_clear(p_pony); + mproc_clear(p_control); + mproc_clear(p_lka); + mproc_clear(p_scheduler); + mproc_clear(p_queue); do { pid = waitpid(WAIT_MYPGRP, NULL, 0); @@ -292,8 +292,8 @@ parent_shutdown(int ret) unlink(SMTPD_SOCKET); - log_warnx("warn: parent terminating"); - exit(ret); + log_info("Exiting"); + exit(0); } static void @@ -333,16 +333,17 @@ static void parent_sig_handler(int sig, short event, void *p) { struct child *child; - int die = 0, die_gracefully = 0, status, fail; + int status, fail; pid_t pid; char *cause; switch (sig) { case SIGTERM: case SIGINT: - log_info("info: %s, shutting down", strsignal(sig)); - die_gracefully = 1; - /* FALLTHROUGH */ + log_debug("debug: got signal %d", sig); + parent_shutdown(); + /* NOT REACHED */ + case SIGCHLD: do { int len; @@ -379,7 +380,6 @@ parent_sig_handler(int sig, short event, switch (child->type) { case CHILD_DAEMON: - die = 1; if (fail) log_warnx("warn: lost child: %s %s", child->title, cause); @@ -434,10 +434,6 @@ parent_sig_handler(int sig, short event, free(cause); } while (pid > 0 || (pid == -1 && errno == EINTR)); - if (die) - parent_shutdown(1); - else if (die_gracefully) - parent_shutdown(0); break; default: fatalx("smtpd: unexpected signal"); @@ -1597,7 +1593,7 @@ imsg_dispatch(struct mproc *p, struct im int msg; if (imsg == NULL) { - exit(1); + imsg_callback(p, imsg); return; }