From 437e256a49f49685e10a6c599eea0ef9638bc1f7 Mon Sep 17 00:00:00 2001 From: benno Date: Fri, 23 May 2014 18:37:20 +0000 Subject: [PATCH] clean up after the traphandler children, otherwise they will live on as zombies. ok blambert --- usr.sbin/snmpd/snmpd.c | 44 +++++++++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/usr.sbin/snmpd/snmpd.c b/usr.sbin/snmpd/snmpd.c index b59733cea50..37c5290b913 100644 --- a/usr.sbin/snmpd/snmpd.c +++ b/usr.sbin/snmpd/snmpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: snmpd.c,v 1.22 2014/04/28 08:25:05 blambert Exp $ */ +/* $OpenBSD: snmpd.c,v 1.23 2014/05/23 18:37:20 benno Exp $ */ /* * Copyright (c) 2007, 2008, 2012 Reyk Floeter @@ -61,7 +61,9 @@ snmpd_sig_handler(int sig, short event, void *arg) { struct privsep *ps = arg; struct snmpd *env = ps->ps_env; - int die = 0, id; + int die = 0, status, fail, id; + pid_t pid; + char *cause; switch (sig) { case SIGTERM: @@ -69,11 +71,39 @@ snmpd_sig_handler(int sig, short event, void *arg) die = 1; /* FALLTHROUGH */ case SIGCHLD: - for (id = 0; id < PROC_MAX; id++) { - if (check_child(ps->ps_pid[id], - ps->ps_title[id])) - die = 1; - } + do { + pid = waitpid(WAIT_ANY, &status, WNOHANG); + if (pid <= 0) + continue; + + fail = 0; + if (WIFSIGNALED(status)) { + fail = 1; + asprintf(&cause, "terminated; signal %d", + WTERMSIG(status)); + } else if (WIFEXITED(status)) { + if (WEXITSTATUS(status) != 0) { + fail = 1; + asprintf(&cause, "exited abnormally"); + } else + asprintf(&cause, "exited okay"); + } else + fatalx("unexpected cause of SIGCHLD"); + + for (id = 0; id < PROC_MAX; id++) { + if (pid == ps->ps_pid[id] && + check_child(ps->ps_pid[id], + ps->ps_title[id])) { + die = 1; + if (fail) + log_warnx("lost child: %s %s", + ps->ps_title[id], cause); + break; + } + } + free(cause); + } while (pid > 0 || (pid == -1 && errno == EINTR)); + if (die) snmpd_shutdown(env); break; -- 2.20.1