summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbenno <benno@openbsd.org>2014-05-23 18:37:20 +0000
committerbenno <benno@openbsd.org>2014-05-23 18:37:20 +0000
commit437e256a49f49685e10a6c599eea0ef9638bc1f7 (patch)
tree52dfc03c6d4a5525b03837e74c096bee2123e474
parentTake an axe to rc5speed.c - strip out everything that is for other (diff)
downloadwireguard-openbsd-437e256a49f49685e10a6c599eea0ef9638bc1f7.tar.xz
wireguard-openbsd-437e256a49f49685e10a6c599eea0ef9638bc1f7.zip
clean up after the traphandler children, otherwise they will live on
as zombies. ok blambert
-rw-r--r--usr.sbin/snmpd/snmpd.c44
1 files 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 <reyk@openbsd.org>
@@ -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;