If proc_init() knows about debug mode, we can move the call to daemon(3) into proc_init(). Then only the parent calls daemon(3). The children will inherit stdin/out/err from the parent and don't have to do anything. And since the children don't call daemon(3) themselves anymore, there won't be any zombies.
Below is an updated, more simpler patch. The only problem here is that half of the daemons set the 'nochdir' flag of daemon(3), while the other half doesn't. Hence the proc.c files differ in the arguments passed to daemon(3). If this is a problem, I can make this a parameter passed to proc_init(). Gerhard Index: usr.sbin/httpd/httpd.c =================================================================== RCS file: /cvs/src/usr.sbin/httpd/httpd.c,v retrieving revision 1.67 diff -u -p -u -p -r1.67 httpd.c --- usr.sbin/httpd/httpd.c 28 May 2017 10:37:26 -0000 1.67 +++ usr.sbin/httpd/httpd.c 8 Mar 2018 09:17:07 -0000 @@ -215,11 +215,9 @@ main(int argc, char *argv[]) } /* only the parent returns */ - proc_init(ps, procs, nitems(procs), argc0, argv, proc_id); + proc_init(ps, procs, nitems(procs), argc0, argv, proc_id, debug); log_procinit("parent"); - if (!debug && daemon(1, 0) == -1) - err(1, "failed to daemonize"); if (ps->ps_noaction == 0) log_info("startup"); Index: usr.sbin/httpd/httpd.h =================================================================== RCS file: /cvs/src/usr.sbin/httpd/httpd.h,v retrieving revision 1.135 diff -u -p -u -p -r1.135 httpd.h --- usr.sbin/httpd/httpd.h 7 Feb 2018 03:28:05 -0000 1.135 +++ usr.sbin/httpd/httpd.h 7 Mar 2018 15:49:30 -0000 @@ -761,7 +761,7 @@ __dead void fatalx(const char *, ...) enum privsep_procid proc_getid(struct privsep_proc *, unsigned int, const char *); void proc_init(struct privsep *, struct privsep_proc *, unsigned int, - int, char **, enum privsep_procid); + int, char **, enum privsep_procid, int); void proc_kill(struct privsep *); void proc_connect(struct privsep *); void proc_dispatch(int, short event, void *); Index: usr.sbin/httpd/proc.c =================================================================== RCS file: /cvs/src/usr.sbin/httpd/proc.c,v retrieving revision 1.37 diff -u -p -u -p -r1.37 proc.c --- usr.sbin/httpd/proc.c 28 May 2017 10:37:26 -0000 1.37 +++ usr.sbin/httpd/proc.c 8 Mar 2018 09:17:46 -0000 @@ -191,7 +191,7 @@ proc_connect(struct privsep *ps) void proc_init(struct privsep *ps, struct privsep_proc *procs, unsigned int nproc, - int argc, char **argv, enum privsep_procid proc_id) + int argc, char **argv, enum privsep_procid proc_id, int debug) { struct privsep_proc *p = NULL; struct privsep_pipes *pa, *pb; @@ -205,6 +205,8 @@ proc_init(struct privsep *ps, struct pri if (proc_id == PROC_PARENT) { privsep_process = PROC_PARENT; + if (!debug && daemon(1, 0) == -1) + fatal("failed to daemonize"); proc_setup(ps, procs, nproc); /* Index: usr.sbin/relayd/proc.c =================================================================== RCS file: /cvs/src/usr.sbin/relayd/proc.c,v retrieving revision 1.39 diff -u -p -u -p -r1.39 proc.c --- usr.sbin/relayd/proc.c 28 May 2017 10:39:15 -0000 1.39 +++ usr.sbin/relayd/proc.c 8 Mar 2018 09:19:41 -0000 @@ -191,7 +191,7 @@ proc_connect(struct privsep *ps) void proc_init(struct privsep *ps, struct privsep_proc *procs, unsigned int nproc, - int argc, char **argv, enum privsep_procid proc_id) + int argc, char **argv, enum privsep_procid proc_id, int debug) { struct privsep_proc *p = NULL; struct privsep_pipes *pa, *pb; @@ -205,6 +205,8 @@ proc_init(struct privsep *ps, struct pri if (proc_id == PROC_PARENT) { privsep_process = PROC_PARENT; + if (!debug && daemon(1, 0) == -1) + fatal("failed to daemonize"); proc_setup(ps, procs, nproc); /* Index: usr.sbin/relayd/relayd.c =================================================================== RCS file: /cvs/src/usr.sbin/relayd/relayd.c,v retrieving revision 1.171 diff -u -p -u -p -r1.171 relayd.c --- usr.sbin/relayd/relayd.c 29 Nov 2017 15:24:50 -0000 1.171 +++ usr.sbin/relayd/relayd.c 8 Mar 2018 09:18:21 -0000 @@ -212,11 +212,9 @@ main(int argc, char *argv[]) ps->ps_title[proc_id] = title; /* only the parent returns */ - proc_init(ps, procs, nitems(procs), argc0, argv, proc_id); + proc_init(ps, procs, nitems(procs), argc0, argv, proc_id, debug); log_procinit("parent"); - if (!debug && daemon(1, 0) == -1) - err(1, "failed to daemonize"); if (ps->ps_noaction == 0) log_info("startup"); Index: usr.sbin/relayd/relayd.h =================================================================== RCS file: /cvs/src/usr.sbin/relayd/relayd.h,v retrieving revision 1.248 diff -u -p -u -p -r1.248 relayd.h --- usr.sbin/relayd/relayd.h 28 Nov 2017 18:25:53 -0000 1.248 +++ usr.sbin/relayd/relayd.h 7 Mar 2018 15:42:34 -0000 @@ -1383,7 +1383,7 @@ enum privsep_procid proc_getid(struct privsep_proc *, unsigned int, const char *); int proc_flush_imsg(struct privsep *, enum privsep_procid, int); void proc_init(struct privsep *, struct privsep_proc *, unsigned int, - int, char **, enum privsep_procid); + int, char **, enum privsep_procid, int); void proc_kill(struct privsep *); void proc_connect(struct privsep *); void proc_dispatch(int, short event, void *); Index: usr.sbin/snmpd/proc.c =================================================================== RCS file: /cvs/src/usr.sbin/snmpd/proc.c,v retrieving revision 1.24 diff -u -p -u -p -r1.24 proc.c --- usr.sbin/snmpd/proc.c 29 May 2017 12:56:26 -0000 1.24 +++ usr.sbin/snmpd/proc.c 8 Mar 2018 09:20:40 -0000 @@ -191,7 +191,7 @@ proc_connect(struct privsep *ps) void proc_init(struct privsep *ps, struct privsep_proc *procs, unsigned int nproc, - int argc, char **argv, enum privsep_procid proc_id) + int argc, char **argv, enum privsep_procid proc_id, int debug) { struct privsep_proc *p = NULL; struct privsep_pipes *pa, *pb; @@ -205,6 +205,8 @@ proc_init(struct privsep *ps, struct pri if (proc_id == PROC_PARENT) { privsep_process = PROC_PARENT; + if (!debug && daemon(0, 0) == -1) + fatal("failed to daemonize"); proc_setup(ps, procs, nproc); /* Index: usr.sbin/snmpd/snmpd.c =================================================================== RCS file: /cvs/src/usr.sbin/snmpd/snmpd.c,v retrieving revision 1.37 diff -u -p -u -p -r1.37 snmpd.c --- usr.sbin/snmpd/snmpd.c 12 Aug 2017 04:29:57 -0000 1.37 +++ usr.sbin/snmpd/snmpd.c 8 Mar 2018 09:20:13 -0000 @@ -230,9 +230,7 @@ main(int argc, char *argv[]) pf_init(); snmpd_generate_engineid(env); - proc_init(ps, procs, nitems(procs), argc0, argv0, proc_id); - if (!debug && daemon(0, 0) == -1) - err(1, "failed to daemonize"); + proc_init(ps, procs, nitems(procs), argc0, argv0, proc_id, debug); log_procinit("parent"); log_info("startup"); Index: usr.sbin/snmpd/snmpd.h =================================================================== RCS file: /cvs/src/usr.sbin/snmpd/snmpd.h,v retrieving revision 1.77 diff -u -p -u -p -r1.77 snmpd.h --- usr.sbin/snmpd/snmpd.h 8 Feb 2018 00:21:10 -0000 1.77 +++ usr.sbin/snmpd/snmpd.h 7 Mar 2018 15:45:01 -0000 @@ -759,7 +759,7 @@ void usm_make_report(struct snmp_messa enum privsep_procid proc_getid(struct privsep_proc *, unsigned int, const char *); void proc_init(struct privsep *, struct privsep_proc *, unsigned int, - int, char **, enum privsep_procid); + int, char **, enum privsep_procid, int); void proc_kill(struct privsep *); void proc_connect(struct privsep *); void proc_dispatch(int, short event, void *); Index: usr.sbin/switchd/proc.c =================================================================== RCS file: /cvs/src/usr.sbin/switchd/proc.c,v retrieving revision 1.12 diff -u -p -u -p -r1.12 proc.c --- usr.sbin/switchd/proc.c 29 May 2017 12:56:26 -0000 1.12 +++ usr.sbin/switchd/proc.c 8 Mar 2018 09:21:41 -0000 @@ -191,7 +191,7 @@ proc_connect(struct privsep *ps) void proc_init(struct privsep *ps, struct privsep_proc *procs, unsigned int nproc, - int argc, char **argv, enum privsep_procid proc_id) + int argc, char **argv, enum privsep_procid proc_id, int debug) { struct privsep_proc *p = NULL; struct privsep_pipes *pa, *pb; @@ -205,6 +205,8 @@ proc_init(struct privsep *ps, struct pri if (proc_id == PROC_PARENT) { privsep_process = PROC_PARENT; + if (!debug && daemon(0, 0) == -1) + fatal("failed to daemonize"); proc_setup(ps, procs, nproc); /* Index: usr.sbin/switchd/proc.h =================================================================== RCS file: /cvs/src/usr.sbin/switchd/proc.h,v retrieving revision 1.6 diff -u -p -u -p -r1.6 proc.h --- usr.sbin/switchd/proc.h 9 Jan 2017 14:49:22 -0000 1.6 +++ usr.sbin/switchd/proc.h 7 Mar 2018 15:51:16 -0000 @@ -127,7 +127,7 @@ extern struct ctl_connlist ctl_conns; /* proc.c */ void proc_init(struct privsep *, struct privsep_proc *, unsigned int, - int, char **, enum privsep_procid); + int, char **, enum privsep_procid, int); void proc_kill(struct privsep *); void proc_connect(struct privsep *ps); void proc_dispatch(int, short event, void *); Index: usr.sbin/switchd/switchd.c =================================================================== RCS file: /cvs/src/usr.sbin/switchd/switchd.c,v retrieving revision 1.15 diff -u -p -u -p -r1.15 switchd.c --- usr.sbin/switchd/switchd.c 9 Jan 2017 14:49:22 -0000 1.15 +++ usr.sbin/switchd/switchd.c 8 Mar 2018 09:21:09 -0000 @@ -184,10 +184,7 @@ main(int argc, char *argv[]) ps->ps_title[proc_id] = title; /* Only the parent returns. */ - proc_init(ps, procs, nitems(procs), argc0, argv, proc_id); - - if (!debug && daemon(0, 0) == -1) - fatal("failed to daemonize"); + proc_init(ps, procs, nitems(procs), argc0, argv, proc_id, debug); log_procinit("parent"); Index: usr.sbin/vmd/proc.c =================================================================== RCS file: /cvs/src/usr.sbin/vmd/proc.c,v retrieving revision 1.16 diff -u -p -u -p -r1.16 proc.c --- usr.sbin/vmd/proc.c 4 Nov 2017 07:40:31 -0000 1.16 +++ usr.sbin/vmd/proc.c 8 Mar 2018 09:25:05 -0000 @@ -191,7 +191,7 @@ proc_connect(struct privsep *ps) void proc_init(struct privsep *ps, struct privsep_proc *procs, unsigned int nproc, - int argc, char **argv, enum privsep_procid proc_id) + int argc, char **argv, enum privsep_procid proc_id, int debug) { struct privsep_proc *p = NULL; struct privsep_pipes *pa, *pb; @@ -205,6 +205,8 @@ proc_init(struct privsep *ps, struct pri if (proc_id == PROC_PARENT) { privsep_process = PROC_PARENT; + if (!env->vmd_debug && daemon(0, 0) == -1) + fatal("failed to daemonize"); proc_setup(ps, procs, nproc); /* Index: usr.sbin/vmd/proc.h =================================================================== RCS file: /cvs/src/usr.sbin/vmd/proc.h,v retrieving revision 1.12 diff -u -p -u -p -r1.12 proc.h --- usr.sbin/vmd/proc.h 27 Mar 2017 00:28:04 -0000 1.12 +++ usr.sbin/vmd/proc.h 7 Mar 2018 15:53:14 -0000 @@ -159,7 +159,7 @@ struct privsep_fd { /* proc.c */ void proc_init(struct privsep *, struct privsep_proc *, unsigned int, - int, char **, enum privsep_procid); + int, char **, enum privsep_procid, int); void proc_kill(struct privsep *); void proc_connect(struct privsep *ps); void proc_dispatch(int, short event, void *); Index: usr.sbin/vmd/vmd.c =================================================================== RCS file: /cvs/src/usr.sbin/vmd/vmd.c,v retrieving revision 1.80 diff -u -p -u -p -r1.80 vmd.c --- usr.sbin/vmd/vmd.c 18 Feb 2018 01:00:25 -0000 1.80 +++ usr.sbin/vmd/vmd.c 8 Mar 2018 09:22:16 -0000 @@ -755,11 +755,10 @@ main(int argc, char **argv) ps->ps_title[proc_id] = title; /* only the parent returns */ - proc_init(ps, procs, nitems(procs), argc0, argv, proc_id); + proc_init(ps, procs, nitems(procs), argc0, argv, proc_id, + env->vmd_debug); log_procinit("parent"); - if (!env->vmd_debug && daemon(0, 0) == -1) - fatal("can't daemonize"); if (ps->ps_noaction == 0) log_info("startup");