View | Details | Raw Unified | Return to bug 268580
Collapse All | Expand All

(-)b/usr.sbin/daemon/daemon.8 (+6 lines)
Lines 60-65 The options are as follows: Link Here
60
.It Fl c
60
.It Fl c
61
Change the current working directory to the root
61
Change the current working directory to the root
62
.Pq Dq Pa / .
62
.Pq Dq Pa / .
63
.It Fl d Ar shutdown_delay
64
When the daemon process receives SIGTERM forward the SIGTERM signal to
65
the supervised process. If it has not exited in delay seconds send SIGKILL
66
to the supervised process. The daemon process will wait for the supervised process
67
to exit continuing to log any output if requested.
63
.It Fl f
68
.It Fl f
64
Redirect standard input, standard output and standard error to
69
Redirect standard input, standard output and standard error to
65
.Pa /dev/null .
70
.Pa /dev/null .
Lines 169-174 If any of the options Link Here
169
.Fl T ,
174
.Fl T ,
170
.Fl m ,
175
.Fl m ,
171
.Fl S ,
176
.Fl S ,
177
.Fl d ,
172
or
178
or
173
.Fl l
179
.Fl l
174
are specified, the program is executed in a spawned child process.
180
are specified, the program is executed in a spawned child process.
(-)b/usr.sbin/daemon/daemon.c (-5 / +56 lines)
Lines 69-74 static void restrict_process(const char *); Link Here
69
static void handle_term(int);
69
static void handle_term(int);
70
static void handle_chld(int);
70
static void handle_chld(int);
71
static void handle_hup(int);
71
static void handle_hup(int);
72
static void handle_alarm(int);
72
static int open_log(const char *);
73
static int open_log(const char *);
73
static void reopen_log(struct log_params *);
74
static void reopen_log(struct log_params *);
74
static int  listen_child(int, struct log_params *);
75
static int  listen_child(int, struct log_params *);
Lines 86-92 int Link Here
86
main(int argc, char *argv[])
87
main(int argc, char *argv[])
87
{
88
{
88
	const char *pidfile, *ppidfile, *title, *user, *outfn, *logtag;
89
	const char *pidfile, *ppidfile, *title, *user, *outfn, *logtag;
89
	int ch, nochdir, noclose, restart, dosyslog, child_eof;
90
	int ch, nochdir, noclose, restart, dosyslog, child_eof, delay;
90
	sigset_t mask_susp, mask_orig, mask_read, mask_term;
91
	sigset_t mask_susp, mask_orig, mask_read, mask_term;
91
	struct log_params logpar;
92
	struct log_params logpar;
92
	int pfd[2] = { -1, -1 }, outfd = -1;
93
	int pfd[2] = { -1, -1 }, outfd = -1;
Lines 104-112 main(int argc, char *argv[]) Link Here
104
	restart = 0;
105
	restart = 0;
105
	dosyslog = 0;
106
	dosyslog = 0;
106
	log_reopen = 0;
107
	log_reopen = 0;
108
        delay = 0;
107
	outfn = NULL;
109
	outfn = NULL;
108
	title = NULL;
110
	title = NULL;
109
	while ((ch = getopt(argc, argv, "cfHSp:P:ru:o:s:l:t:l:m:R:T:")) != -1) {
111
	while ((ch = getopt(argc, argv, "cfHSp:P:ru:o:s:l:t:l:m:R:T:d:")) != -1) {
110
		switch (ch) {
112
		switch (ch) {
111
		case 'c':
113
		case 'c':
112
			nochdir = 0;
114
			nochdir = 0;
Lines 164-169 main(int argc, char *argv[]) Link Here
164
		case 'u':
166
		case 'u':
165
			user = optarg;
167
			user = optarg;
166
			break;
168
			break;
169
		case 'd':
170
			delay = strtol(optarg, &p, 0);
171
			if (p == optarg || delay < 0)
172
				errx(6, "invalid shutdown delay");
173
			break;
167
		default:
174
		default:
168
			usage();
175
			usage();
169
		}
176
		}
Lines 210-216 main(int argc, char *argv[]) Link Here
210
	 * and syslog.
217
	 * and syslog.
211
	 */
218
	 */
212
	pid = -1;
219
	pid = -1;
213
	if (pidfile || ppidfile || restart || outfd != -1 || dosyslog) {
220
	if (pidfile || ppidfile || restart || outfd != -1 || dosyslog || delay) {
214
		struct sigaction act_term, act_chld, act_hup;
221
		struct sigaction act_term, act_chld, act_hup;
215
222
216
		/* Avoid PID racing with SIGCHLD and SIGTERM. */
223
		/* Avoid PID racing with SIGCHLD and SIGTERM. */
Lines 355-361 main(int argc, char *argv[]) Link Here
355
		if (child_gone && child_eof) {
362
		if (child_gone && child_eof) {
356
			break;
363
			break;
357
		} else if (terminate) {
364
		} else if (terminate) {
358
			goto exit;
365
			goto cleanup;
359
		} else if (!child_eof) {
366
		} else if (!child_eof) {
360
			if (sigprocmask(SIG_BLOCK, &mask_read, NULL)) {
367
			if (sigprocmask(SIG_BLOCK, &mask_read, NULL)) {
361
				warn("sigprocmask");
368
				warn("sigprocmask");
Lines 390-395 main(int argc, char *argv[]) Link Here
390
		pfd[0] = -1;
397
		pfd[0] = -1;
391
		goto restart;
398
		goto restart;
392
	}
399
	}
400
401
cleanup:
402
	/*
403
	 * If shutdown delay is set and the child process is still running
404
	 * wait for up to delay seconds for it to exit. While we wait try and
405
	 * output any last messages from the process.  If we get to the
406
	 * elapsed time send sigkill to the child process. At that point we
407
	 * should get a SIGCHLD signal to set child_gone and we break out of
408
	 * our read loop.
409
	 */
410
	if (!child_gone && delay) {
411
		struct sigaction act_alarm;
412
		memset(&act_alarm, 0, sizeof(act_alarm));
413
		act_alarm.sa_handler = handle_alarm;
414
		sigemptyset(&act_alarm.sa_mask);
415
		/* Don't want to race with SIGCHLD handler setting child_gone */
416
		sigaddset(&act_alarm.sa_mask, SIGCHLD);
417
418
		if (sigaction(SIGALRM, &act_alarm, NULL) == -1) {
419
			warn("sigaction");
420
			goto exit;
421
		}
422
		alarm(delay);
423
		while (!child_eof) {
424
			child_eof = !listen_child(pfd[0], &logpar);
425
		}
426
		/* Block SIGCHLD while we test if child is gone */
427
		if (sigprocmask(SIG_BLOCK, &mask_susp, &mask_orig)) {
428
			warn("sigprocmask");
429
			goto exit;
430
		}
431
		while(!child_gone) {
432
			sigsuspend(&mask_orig);
433
		}
434
		alarm(0);
435
	}
393
exit:
436
exit:
394
	close(outfd);
437
	close(outfd);
395
	close(pfd[0]);
438
	close(pfd[0]);
Lines 556-561 do_output(const unsigned char *buf, size_t len, struct log_params *logpar) Link Here
556
		printf("%.*s", (int)len, buf);
599
		printf("%.*s", (int)len, buf);
557
}
600
}
558
601
602
static void
603
handle_alarm(int signo __unused)
604
{
605
	if (pid > 0 && !child_gone) {
606
		kill(pid, SIGKILL);
607
	}
608
}
609
559
/*
610
/*
560
 * We use the global PID acquired directly from fork. If there is no valid
611
 * We use the global PID acquired directly from fork. If there is no valid
561
 * child pid, the handler should be blocked and/or child_gone == 1.
612
 * child pid, the handler should be blocked and/or child_gone == 1.
Lines 615-621 usage(void) Link Here
615
{
666
{
616
	(void)fprintf(stderr,
667
	(void)fprintf(stderr,
617
	    "usage: daemon [-cfHrS] [-p child_pidfile] [-P supervisor_pidfile]\n"
668
	    "usage: daemon [-cfHrS] [-p child_pidfile] [-P supervisor_pidfile]\n"
618
	    "              [-u user] [-o output_file] [-t title]\n"
669
	    "              [-u user] [-o output_file] [-t title] [-d shutdown_delay]\n"
619
	    "              [-l syslog_facility] [-s syslog_priority]\n"
670
	    "              [-l syslog_facility] [-s syslog_priority]\n"
620
	    "              [-T syslog_tag] [-m output_mask] [-R restart_delay_secs]\n"
671
	    "              [-T syslog_tag] [-m output_mask] [-R restart_delay_secs]\n"
621
	    "command arguments ...\n");
672
	    "command arguments ...\n");

Return to bug 268580