From owner-svn-src-head@FreeBSD.ORG Sun Feb 19 10:36:30 2012 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 60E9F106566C; Sun, 19 Feb 2012 10:36:30 +0000 (UTC) (envelope-from trociny@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 458878FC08; Sun, 19 Feb 2012 10:36:30 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q1JAaUJb076332; Sun, 19 Feb 2012 10:36:30 GMT (envelope-from trociny@svn.freebsd.org) Received: (from trociny@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q1JAaUKY076329; Sun, 19 Feb 2012 10:36:30 GMT (envelope-from trociny@svn.freebsd.org) Message-Id: <201202191036.q1JAaUKY076329@svn.freebsd.org> From: Mikolaj Golub Date: Sun, 19 Feb 2012 10:36:30 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r231911 - head/usr.sbin/daemon X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 19 Feb 2012 10:36:30 -0000 Author: trociny Date: Sun Feb 19 10:36:29 2012 New Revision: 231911 URL: http://svn.freebsd.org/changeset/base/231911 Log: Add -r option to restart the program if it has been terminated. Suggested by: Andrey Zonov MFC after: 2 weeks Modified: head/usr.sbin/daemon/daemon.8 head/usr.sbin/daemon/daemon.c Modified: head/usr.sbin/daemon/daemon.8 ============================================================================== --- head/usr.sbin/daemon/daemon.8 Sun Feb 19 10:23:51 2012 (r231910) +++ head/usr.sbin/daemon/daemon.8 Sun Feb 19 10:36:29 2012 (r231911) @@ -71,16 +71,28 @@ owner is the user who runs the regardless of whether the .Fl u option is used or not. -If the monitoring +.It Fl r +Supervise and restart the program if it has been terminated. +.It Fl u Ar user +Login name of the user to execute the program under. +Requires adequate superuser privileges. +.El +.Pp +If the +.Fl p +or +.Fl r +option is specified the program is executed in a spawned child process. +The +.Nm +waits until it terminates to keep the pid file locked and removes it +after the process exits or restarts the program. +In this case if the monitoring .Nm receives software termination signal (SIGTERM) it forwards it to the spawned process. Normally it will cause the child to exit followed by the termination of the supervising process after removing the pidfile. -.It Fl u Ar user -Login name of the user to execute the program under. -Requires adequate superuser privileges. -.El .Sh EXIT STATUS The .Nm Modified: head/usr.sbin/daemon/daemon.c ============================================================================== --- head/usr.sbin/daemon/daemon.c Sun Feb 19 10:23:51 2012 (r231910) +++ head/usr.sbin/daemon/daemon.c Sun Feb 19 10:36:29 2012 (r231911) @@ -46,7 +46,7 @@ __FBSDID("$FreeBSD$"); static void dummy_sighandler(int); static void restrict_process(const char *); -static void wait_child(pid_t pid, sigset_t *mask); +static int wait_child(pid_t pid, sigset_t *mask); static void usage(void); int @@ -54,13 +54,14 @@ main(int argc, char *argv[]) { struct pidfh *pfh = NULL; sigset_t mask, oldmask; - int ch, nochdir, noclose; + int ch, nochdir, noclose, restart; const char *pidfile, *user; pid_t otherpid, pid; nochdir = noclose = 1; + restart = 0; pidfile = user = NULL; - while ((ch = getopt(argc, argv, "-cfp:u:")) != -1) { + while ((ch = getopt(argc, argv, "-cfp:ru:")) != -1) { switch (ch) { case 'c': nochdir = 0; @@ -71,6 +72,9 @@ main(int argc, char *argv[]) case 'p': pidfile = optarg; break; + case 'r': + restart = 1; + break; case 'u': user = optarg; break; @@ -104,15 +108,16 @@ main(int argc, char *argv[]) err(1, NULL); /* - * If the pidfile option is specified the daemon executes the - * command in a forked process and wait on child exit to - * remove the pidfile. Normally we don't want the monitoring - * daemon to be terminated leaving the running process and the - * stale pidfile, so we catch SIGTERM and pass it to the - * children expecting to get SIGCHLD eventually. + * If the pidfile or restart option is specified the daemon + * executes the command in a forked process and wait on child + * exit to remove the pidfile or restart the command. Normally + * we don't want the monitoring daemon to be terminated + * leaving the running process and the stale pidfile, so we + * catch SIGTERM and forward it to the children expecting to + * get SIGCHLD eventually. */ pid = -1; - if (pidfile != NULL) { + if (pidfile != NULL || restart) { /* * Restore default action for SIGTERM in case the * parent process decided to ignore it. @@ -133,6 +138,7 @@ main(int argc, char *argv[]) sigaddset(&mask, SIGCHLD); if (sigprocmask(SIG_SETMASK, &mask, &oldmask) == -1) err(1, "sigprocmask"); +restart: /* * Spawn a child to exec the command, so in the parent * we could wait for it to exit and remove pidfile. @@ -164,7 +170,10 @@ main(int argc, char *argv[]) err(1, "%s", argv[0]); } setproctitle("%s[%d]", argv[0], pid); - wait_child(pid, &mask); + if (wait_child(pid, &mask) == 0 && restart) { + sleep(1); + goto restart; + } pidfile_remove(pfh); exit(0); /* Exit status does not matter. */ } @@ -188,28 +197,30 @@ restrict_process(const char *user) errx(1, "failed to set user environment"); } -static void +static int wait_child(pid_t pid, sigset_t *mask) { - int signo; + int terminate, signo; + terminate = 0; for (;;) { if (sigwait(mask, &signo) == -1) { warn("sigwaitinfo"); - return; + return (-1); } switch (signo) { case SIGCHLD: - return; + return (terminate); case SIGTERM: + terminate = 1; if (kill(pid, signo) == -1) { warn("kill"); - return; + return (-1); } continue; default: warnx("sigwaitinfo: invalid signal: %d", signo); - return; + return (-1); } } }