From nobody@FreeBSD.org  Fri Aug 16 14:49:02 2013
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115])
	(using TLSv1 with cipher ADH-AES256-SHA (256/256 bits))
	(No client certificate requested)
	by hub.freebsd.org (Postfix) with ESMTP id B062CBF6
	for <freebsd-gnats-submit@FreeBSD.org>; Fri, 16 Aug 2013 14:49:02 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from oldred.freebsd.org (oldred.freebsd.org [8.8.178.121])
	(using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))
	(No client certificate requested)
	by mx1.freebsd.org (Postfix) with ESMTPS id 9E2C52B91
	for <freebsd-gnats-submit@FreeBSD.org>; Fri, 16 Aug 2013 14:49:02 +0000 (UTC)
Received: from oldred.freebsd.org ([127.0.1.6])
	by oldred.freebsd.org (8.14.5/8.14.7) with ESMTP id r7GEn2qe032905
	for <freebsd-gnats-submit@FreeBSD.org>; Fri, 16 Aug 2013 14:49:02 GMT
	(envelope-from nobody@oldred.freebsd.org)
Received: (from nobody@localhost)
	by oldred.freebsd.org (8.14.5/8.14.5/Submit) id r7GEn2Xe032902;
	Fri, 16 Aug 2013 14:49:02 GMT
	(envelope-from nobody)
Message-Id: <201308161449.r7GEn2Xe032902@oldred.freebsd.org>
Date: Fri, 16 Aug 2013 14:49:02 GMT
From: Mark Felder <feld@FreeBSD.org>
To: freebsd-gnats-submit@FreeBSD.org
Subject: [patch] daemon(8): ability to write pidfile for itself
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         181341
>Category:       bin
>Synopsis:       [patch] daemon(8): ability to write pidfile for itself
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    jmg
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Fri Aug 16 14:50:00 UTC 2013
>Closed-Date:    Thu Oct 03 19:10:15 UTC 2013
>Last-Modified:  Thu Oct 03 19:10:15 UTC 2013
>Originator:     Mark Felder
>Release:        
>Organization:
>Environment:
>Description:
I was updating an rc script for a port (net/nss-pam-ldapd) to use daemon(8) and after discussing with zi@ we decided it would be best if this rc script used daemon's ability to supervise and restart the child process (-r option). Unfortunately when the -r functionality was added to daemon(8) the ability to write a pidfile for the daemon(8) supervisor itself was overlooked. This is crucial for this option to be useful in an rc script because the default pidfile written is of the child which the rc framework would directly signal to terminate, but the daemon supervisor will just restart it again! We wanted the child process to be able to restart on its own if it crashed or was accidentally killed, but still be able to cleanly shut it down. The only workaround is to write your own stop_cmd and status_cmd routines which are ugly, inconsistent throughout the ports tree, and sadly unable to leverage the robust built-in features of the rc framework.
>How-To-Repeat:
updating security/nss-pam-ldapd rc script with desired functionality BEFORE this patch will have to look something like this:

command="/usr/sbin/daemon -f -r"
command_args="%%PREFIX%%/bin/nslcd -d"
status_cmd=nslcd_status
stop_cmd=nslcd_stop

nslcd_status()
{
        mypid=$(pgrep -f "daemon: ${command}")
        if [ ! ${mypid} = '' ]; then
                echo "${name} is running with PID ${mypid}";
        else
                echo "${name} not running";
        fi
}

nslcd_stop()
{
        mypid=$(pgrep -f "daemon: ${command}")
        if [ ! ${mypid} = '' ]; then
                echo "Stopping ${name}";
                kill -TERM ${mypid};
                wait_for_pids ${mypid};
        else
                echo "${name} not running";
        fi
}

run_rc_command "$1"
>Fix:
Apply attached patch. This rc script could then be as simple as this:

pidfile="/var/run/nslcd_daemon.pid"
command="/usr/sbin/daemon -f -r -P ${pidfile}"
command_args="%%PREFIX%%/bin/nslcd -d"

run_rc_command "$1"


Of course changes like this throughout the ports tree will have to wait for all supported releases to include this functionality, but it should be perfectly safe to MFC this to a 9.x release.

daemon.c portion of the patch was written by a friend per my request who is interested in doing some FreeBSD hacking, but wishes to remain anonymous.

Patch attached with submission follows:

Index: daemon.8
===================================================================
--- daemon.8	(revision 254331)
+++ daemon.8	(working copy)
@@ -35,7 +35,8 @@
 .Sh SYNOPSIS
 .Nm
 .Op Fl cfr
-.Op Fl p Ar pidfile
+.Op Fl p Ar child pidfile
+.Op Fl P Ar supervisor pidfile
 .Op Fl u Ar user
 .Ar command arguments ...
 .Sh DESCRIPTION
@@ -71,6 +72,26 @@
 regardless of whether the
 .Fl u
 option is used or not.
+.It Fl P Ar file
+Write the ID of the 
+.Nm
+process into the
+.Ar file
+using the
+.Xr pidfile 3
+functionality.
+The program is executed in a spawned child process while the
+.Nm
+waits until it terminates to keep the
+.Ar file
+locked and removes it after the process exits.
+The
+.Ar file
+owner is the user who runs the
+.Nm
+regardless of whether the
+.Fl u
+option is used or not.
 .It Fl r
 Supervise and restart the program if it has been terminated.
 .It Fl u Ar user
@@ -80,6 +101,7 @@
 .Pp
 If the
 .Fl p
+.Fl P
 or
 .Fl r
 option is specified the program is executed in a spawned child process.
@@ -93,6 +115,25 @@
 spawned process.
 Normally it will cause the child to exit followed by the termination
 of the supervising process after removing the pidfile.
+.Pp
+The
+.Fl P
+option is useful combined with the
+.Fl r
+option as the pidfile contains the ID of the supervisor
+not the child. This is especially important if you use
+.Fl r
+in an rc script as the
+.Fl p
+option will give you the child's ID to signal when you attempt to
+stop the service, causing 
+.Nm
+to restart the child. If the ID written by the
+.Fl P
+option is signalled,
+.Nm
+will cause the child to exit followed by the termination of the
+supervising process after removing the pidfile.
 .Sh EXIT STATUS
 The
 .Nm
Index: daemon.c
===================================================================
--- daemon.c	(revision 254331)
+++ daemon.c	(working copy)
@@ -53,16 +53,17 @@
 int
 main(int argc, char *argv[])
 {
-	struct pidfh *pfh = NULL;
+	struct pidfh  *ppfh, *pfh;
 	sigset_t mask, oldmask;
 	int ch, nochdir, noclose, restart;
-	const char *pidfile, *user;
+	const char *pidfile, *ppidfile,  *user;
 	pid_t otherpid, pid;
 
 	nochdir = noclose = 1;
 	restart = 0;
-	pidfile = user = NULL;
-	while ((ch = getopt(argc, argv, "cfp:ru:")) != -1) {
+	ppfh = pfh = NULL;
+	ppidfile = pidfile = user = NULL;
+	while ((ch = getopt(argc, argv, "-cfp:P:ru:")) != -1) {
 		switch (ch) {
 		case 'c':
 			nochdir = 0;
@@ -73,6 +74,9 @@
 		case 'p':
 			pidfile = optarg;
 			break;
+		case 'P':
+			ppidfile = optarg;
+			break;
 		case 'r':
 			restart = 1;
 			break;
@@ -89,7 +93,7 @@
 	if (argc == 0)
 		usage();
 
-	pfh = NULL;
+	ppfh = pfh = NULL;
 	/*
 	 * Try to open the pidfile before calling daemon(3),
 	 * to be able to report the error intelligently
@@ -104,6 +108,18 @@
 			err(2, "pidfile ``%s''", pidfile);
 		}
 	}
+	
+	/* do same for actual daemon process */
+	if (ppidfile != NULL) {
+		ppfh = pidfile_open(ppidfile, 0600, &otherpid);
+		if (ppfh == NULL) {
+			if (errno == EEXIST) {
+				errx(3, "process already running, pid: %d",
+				     otherpid);
+			}
+			err(2, "ppidfile ``%s''", ppidfile);
+		}
+	}
 
 	if (daemon(nochdir, noclose) == -1)
 		err(1, NULL);
@@ -176,6 +192,11 @@
 		 */
 		err(1, "%s", argv[0]);
 	}
+	/* write out parent pidfile if needed */
+	if (ppidfile != NULL) {
+		pidfile_write(ppfh);
+	}
+
 	setproctitle("%s[%d]", argv[0], pid);
 	if (wait_child(pid, &mask) == 0 && restart) {
 		sleep(1);
@@ -182,6 +203,7 @@
 		goto restart;
 	}
 	pidfile_remove(pfh);
+	pidfile_remove(ppfh);
 	exit(0); /* Exit status does not matter. */
 }
 
@@ -240,7 +262,7 @@
 usage(void)
 {
 	(void)fprintf(stderr,
-	    "usage: daemon [-cfr] [-p pidfile] [-u user] command "
+	    "usage: daemon [-cfr] [-p child pidfile] [-P supervisor pidfile] [-u user] command "
 		"arguments ...\n");
 	exit(1);
 }


>Release-Note:
>Audit-Trail:

From: Mark Felder <feld@FreeBSD.org>
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/181341: [patch] daemon(8): ability to write pidfile for itself
Date: Thu, 05 Sep 2013 11:36:06 -0500

 This is a multi-part message in MIME format.
 
 --_----------=_1378398966221370
 Content-Transfer-Encoding: 7bit
 Content-Type: text/plain
 
 updated patch with some changes suggested by jmg@
 
 --_----------=_1378398966221370
 Content-Disposition: attachment; filename="daemon.diff"
 Content-Id: <1378398963.21962.10bf27b601ae77f55bca374e7d0c8f551230d9cc.033E93E8@messagingengine.com>
 Content-Transfer-Encoding: base64
 Content-Type: application/octet-stream; name="daemon.diff"
 
 SW5kZXg6IGRhZW1vbi44Cj09PT09PT09PT09PT09PT09PT09PT09PT09PT09
 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KLS0tIGRh
 ZW1vbi44CShyZXZpc2lvbiAyNTQzMjUpCisrKyBkYWVtb24uOAkod29ya2lu
 ZyBjb3B5KQpAQCAtMzUsNyArMzUsOCBAQAogLlNoIFNZTk9QU0lTCiAuTm0K
 IC5PcCBGbCBjZnIKLS5PcCBGbCBwIEFyIHBpZGZpbGUKKy5PcCBGbCBwIEFy
 IGNoaWxkX3BpZGZpbGUKKy5PcCBGbCBQIEFyIHN1cGVydmlzb3JfcGlkZmls
 ZQogLk9wIEZsIHUgQXIgdXNlcgogLkFyIGNvbW1hbmQgYXJndW1lbnRzIC4u
 LgogLlNoIERFU0NSSVBUSU9OCkBAIC03MSw2ICs3MiwyNiBAQAogcmVnYXJk
 bGVzcyBvZiB3aGV0aGVyIHRoZQogLkZsIHUKIG9wdGlvbiBpcyB1c2VkIG9y
 IG5vdC4KKy5JdCBGbCBQIEFyIGZpbGUKK1dyaXRlIHRoZSBJRCBvZiB0aGUg
 CisuTm0KK3Byb2Nlc3MgaW50byB0aGUKKy5BciBmaWxlCit1c2luZyB0aGUK
 Ky5YciBwaWRmaWxlIDMKK2Z1bmN0aW9uYWxpdHkuCitUaGUgcHJvZ3JhbSBp
 cyBleGVjdXRlZCBpbiBhIHNwYXduZWQgY2hpbGQgcHJvY2VzcyB3aGlsZSB0
 aGUKKy5ObQord2FpdHMgdW50aWwgaXQgdGVybWluYXRlcyB0byBrZWVwIHRo
 ZQorLkFyIGZpbGUKK2xvY2tlZCBhbmQgcmVtb3ZlcyBpdCBhZnRlciB0aGUg
 cHJvY2VzcyBleGl0cy4KK1RoZQorLkFyIGZpbGUKK293bmVyIGlzIHRoZSB1
 c2VyIHdobyBydW5zIHRoZQorLk5tCityZWdhcmRsZXNzIG9mIHdoZXRoZXIg
 dGhlCisuRmwgdQorb3B0aW9uIGlzIHVzZWQgb3Igbm90LgogLkl0IEZsIHIK
 IFN1cGVydmlzZSBhbmQgcmVzdGFydCB0aGUgcHJvZ3JhbSBpZiBpdCBoYXMg
 YmVlbiB0ZXJtaW5hdGVkLgogLkl0IEZsIHUgQXIgdXNlcgpAQCAtNzksNyAr
 MTAwLDggQEAKIC5FbAogLlBwCiBJZiB0aGUKLS5GbCBwCisuRmwgcCAsCisu
 RmwgUAogb3IKIC5GbCByCiBvcHRpb24gaXMgc3BlY2lmaWVkIHRoZSBwcm9n
 cmFtIGlzIGV4ZWN1dGVkIGluIGEgc3Bhd25lZCBjaGlsZCBwcm9jZXNzLgpA
 QCAtOTMsNiArMTE1LDI1IEBACiBzcGF3bmVkIHByb2Nlc3MuCiBOb3JtYWxs
 eSBpdCB3aWxsIGNhdXNlIHRoZSBjaGlsZCB0byBleGl0IGZvbGxvd2VkIGJ5
 IHRoZSB0ZXJtaW5hdGlvbgogb2YgdGhlIHN1cGVydmlzaW5nIHByb2Nlc3Mg
 YWZ0ZXIgcmVtb3ZpbmcgdGhlIHBpZGZpbGUuCisuUHAKK1RoZQorLkZsIFAK
 K29wdGlvbiBpcyB1c2VmdWwgY29tYmluZWQgd2l0aCB0aGUKKy5GbCByCitv
 cHRpb24gYXMgdGhlIHBpZGZpbGUgY29udGFpbnMgdGhlIElEIG9mIHRoZSBz
 dXBlcnZpc29yCitub3QgdGhlIGNoaWxkLiBUaGlzIGlzIGVzcGVjaWFsbHkg
 aW1wb3J0YW50IGlmIHlvdSB1c2UKKy5GbCByCitpbiBhbiByYyBzY3JpcHQg
 YXMgdGhlCisuRmwgcAorb3B0aW9uIHdpbGwgZ2l2ZSB5b3UgdGhlIGNoaWxk
 J3MgSUQgdG8gc2lnbmFsIHdoZW4geW91IGF0dGVtcHQgdG8KK3N0b3AgdGhl
 IHNlcnZpY2UsIGNhdXNpbmcgCisuTm0KK3RvIHJlc3RhcnQgdGhlIGNoaWxk
 LiBJZiB0aGUgSUQgd3JpdHRlbiBieSB0aGUKKy5GbCBQCitvcHRpb24gaXMg
 c2lnbmFsbGVkLAorLk5tCit3aWxsIGNhdXNlIHRoZSBjaGlsZCB0byBleGl0
 IGZvbGxvd2VkIGJ5IHRoZSB0ZXJtaW5hdGlvbiBvZiB0aGUKK3N1cGVydmlz
 aW5nIHByb2Nlc3MgYWZ0ZXIgcmVtb3ZpbmcgdGhlIHBpZGZpbGUuCiAuU2gg
 RVhJVCBTVEFUVVMKIFRoZQogLk5tCkluZGV4OiBkYWVtb24uYwo9PT09PT09
 PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09
 PT09PT09PT09PT09PT09Ci0tLSBkYWVtb24uYwkocmV2aXNpb24gMjU0MzI1
 KQorKysgZGFlbW9uLmMJKHdvcmtpbmcgY29weSkKQEAgLTUzLDE2ICs1Mywx
 NyBAQAogaW50CiBtYWluKGludCBhcmdjLCBjaGFyICphcmd2W10pCiB7Ci0J
 c3RydWN0IHBpZGZoICpwZmggPSBOVUxMOworCXN0cnVjdCBwaWRmaCAgKnBw
 ZmgsICpwZmg7CiAJc2lnc2V0X3QgbWFzaywgb2xkbWFzazsKIAlpbnQgY2gs
 IG5vY2hkaXIsIG5vY2xvc2UsIHJlc3RhcnQ7Ci0JY29uc3QgY2hhciAqcGlk
 ZmlsZSwgKnVzZXI7CisJY29uc3QgY2hhciAqcGlkZmlsZSwgKnBwaWRmaWxl
 LCAgKnVzZXI7CiAJcGlkX3Qgb3RoZXJwaWQsIHBpZDsKIAogCW5vY2hkaXIg
 PSBub2Nsb3NlID0gMTsKIAlyZXN0YXJ0ID0gMDsKLQlwaWRmaWxlID0gdXNl
 ciA9IE5VTEw7Ci0Jd2hpbGUgKChjaCA9IGdldG9wdChhcmdjLCBhcmd2LCAi
 Y2ZwOnJ1OiIpKSAhPSAtMSkgeworCXBwZmggPSBwZmggPSBOVUxMOworCXBw
 aWRmaWxlID0gcGlkZmlsZSA9IHVzZXIgPSBOVUxMOworCXdoaWxlICgoY2gg
 PSBnZXRvcHQoYXJnYywgYXJndiwgImNmcDpQOnJ1OiIpKSAhPSAtMSkgewog
 CQlzd2l0Y2ggKGNoKSB7CiAJCWNhc2UgJ2MnOgogCQkJbm9jaGRpciA9IDA7
 CkBAIC03Myw2ICs3NCw5IEBACiAJCWNhc2UgJ3AnOgogCQkJcGlkZmlsZSA9
 IG9wdGFyZzsKIAkJCWJyZWFrOworCQljYXNlICdQJzoKKwkJCXBwaWRmaWxl
 ID0gb3B0YXJnOworCQkJYnJlYWs7CiAJCWNhc2UgJ3InOgogCQkJcmVzdGFy
 dCA9IDE7CiAJCQlicmVhazsKQEAgLTg5LDcgKzkzLDcgQEAKIAlpZiAoYXJn
 YyA9PSAwKQogCQl1c2FnZSgpOwogCi0JcGZoID0gTlVMTDsKKwlwcGZoID0g
 cGZoID0gTlVMTDsKIAkvKgogCSAqIFRyeSB0byBvcGVuIHRoZSBwaWRmaWxl
 IGJlZm9yZSBjYWxsaW5nIGRhZW1vbigzKSwKIAkgKiB0byBiZSBhYmxlIHRv
 IHJlcG9ydCB0aGUgZXJyb3IgaW50ZWxsaWdlbnRseQpAQCAtMTA0LDYgKzEw
 OCwxOCBAQAogCQkJZXJyKDIsICJwaWRmaWxlIGBgJXMnJyIsIHBpZGZpbGUp
 OwogCQl9CiAJfQorCQorCS8qIGRvIHNhbWUgZm9yIGFjdHVhbCBkYWVtb24g
 cHJvY2VzcyAqLworCWlmIChwcGlkZmlsZSAhPSBOVUxMKSB7CisJCXBwZmgg
 PSBwaWRmaWxlX29wZW4ocHBpZGZpbGUsIDA2MDAsICZvdGhlcnBpZCk7CisJ
 CWlmIChwcGZoID09IE5VTEwpIHsKKwkJCWlmIChlcnJubyA9PSBFRVhJU1Qp
 IHsKKwkJCQllcnJ4KDMsICJwcm9jZXNzIGFscmVhZHkgcnVubmluZywgcGlk
 OiAlZCIsCisJCQkJICAgICBvdGhlcnBpZCk7CisJCQl9CisJCQllcnIoMiwg
 InBwaWRmaWxlIGBgJXMnJyIsIHBwaWRmaWxlKTsKKwkJfQorCX0KIAogCWlm
 IChkYWVtb24obm9jaGRpciwgbm9jbG9zZSkgPT0gLTEpCiAJCWVycigxLCBO
 VUxMKTsKQEAgLTE3Niw2ICsxOTIsMTAgQEAKIAkJICovCiAJCWVycigxLCAi
 JXMiLCBhcmd2WzBdKTsKIAl9CisJLyogd3JpdGUgb3V0IHBhcmVudCBwaWRm
 aWxlIGlmIG5lZWRlZCAqLworCWlmIChwcGlkZmlsZSAhPSBOVUxMKQorCQlw
 aWRmaWxlX3dyaXRlKHBwZmgpOworCiAJc2V0cHJvY3RpdGxlKCIlc1slZF0i
 LCBhcmd2WzBdLCBwaWQpOwogCWlmICh3YWl0X2NoaWxkKHBpZCwgJm1hc2sp
 ID09IDAgJiYgcmVzdGFydCkgewogCQlzbGVlcCgxKTsKQEAgLTE4Miw2ICsy
 MDIsNyBAQAogCQlnb3RvIHJlc3RhcnQ7CiAJfQogCXBpZGZpbGVfcmVtb3Zl
 KHBmaCk7CisJcGlkZmlsZV9yZW1vdmUocHBmaCk7CiAJZXhpdCgwKTsgLyog
 RXhpdCBzdGF0dXMgZG9lcyBub3QgbWF0dGVyLiAqLwogfQogCkBAIC0yNDAs
 NyArMjYxLDcgQEAKIHVzYWdlKHZvaWQpCiB7CiAJKHZvaWQpZnByaW50Zihz
 dGRlcnIsCi0JICAgICJ1c2FnZTogZGFlbW9uIFstY2ZyXSBbLXAgcGlkZmls
 ZV0gWy11IHVzZXJdIGNvbW1hbmQgIgorCSAgICAidXNhZ2U6IGRhZW1vbiBb
 LWNmcl0gWy1wIGNoaWxkX3BpZGZpbGVdIFstUCBzdXBlcnZpc29yX3BpZGZp
 bGVdIFstdSB1c2VyXSBjb21tYW5kICIKIAkJImFyZ3VtZW50cyAuLi5cbiIp
 OwogCWV4aXQoMSk7CiB9Cg==
 
 --_----------=_1378398966221370--
 
Responsible-Changed-From-To: freebsd-bugs->jmg 
Responsible-Changed-By: jmg 
Responsible-Changed-When: Fri Sep 6 19:05:30 UTC 2013 
Responsible-Changed-Why:  
take this as I'm working w/ feld on the patch.. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=181341 

From: John-Mark Gurney <jmg@funkthat.com>
To: feld@FreeBSD.org, bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/181341: [patch] daemon(8): ability to write pidfile for itself
Date: Thu, 12 Sep 2013 14:39:00 -0700

 --n/aVsWSeQ4JHkrmm
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 
 a new patch w/ some wordsmithing from myself...
 
 -- 
   John-Mark Gurney				Voice: +1 415 225 5579
 
      "All that I will do, has been done, All that I have, has not."
 
 --n/aVsWSeQ4JHkrmm
 Content-Type: text/x-diff; charset=us-ascii
 Content-Disposition: attachment; filename="daemon.patch"
 
 Index: daemon.8
 ===================================================================
 --- daemon.8	(revision 255500)
 +++ daemon.8	(working copy)
 @@ -35,7 +35,8 @@
  .Sh SYNOPSIS
  .Nm
  .Op Fl cfr
 -.Op Fl p Ar pidfile
 +.Op Fl p Ar child_pidfile
 +.Op Fl P Ar supervisor_pidfile
  .Op Fl u Ar user
  .Ar command arguments ...
  .Sh DESCRIPTION
 @@ -53,24 +54,44 @@ Change the current working directory to the root
  .It Fl f
  Redirect standard input, standard output and standard error to
  .Pa /dev/null .
 -.It Fl p Ar file
 +.It Fl p Ar child_pidfile
  Write the ID of the created process into the
 -.Ar file
 +.Ar child_pidfile
  using the
  .Xr pidfile 3
  functionality.
  The program is executed in a spawned child process while the
  .Nm
  waits until it terminates to keep the
 -.Ar file
 +.Ar child_pidfile
  locked and removes it after the process exits.
  The
 -.Ar file
 +.Ar child_pidfile
  owner is the user who runs the
  .Nm
  regardless of whether the
  .Fl u
  option is used or not.
 +.It Fl P Ar supervisor_pidfile
 +Write the ID of the 
 +.Nm
 +process into the
 +.Ar supervisor_pidfile
 +using the
 +.Xr pidfile 3
 +functionality.
 +The program is executed in a spawned child process while the
 +.Nm
 +waits until it terminates to keep the
 +.Ar supervisor_pidfile
 +locked and removes it after the process exits.
 +The
 +.Ar supervisor_pidfile
 +owner is the user who runs the
 +.Nm
 +regardless of whether the
 +.Fl u
 +option is used or not.
  .It Fl r
  Supervise and restart the program if it has been terminated.
  .It Fl u Ar user
 @@ -79,27 +100,46 @@ Requires adequate superuser privileges.
  .El
  .Pp
  If the
 -.Fl p
 +.Fl p ,
 +.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
 +waits until it terminates to keep the pid file(s) locked and removes them
  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.
 +Normally it will cause the child to exit, remove the pidfile(s)
 +and then terminate.
 +.Pp
 +The
 +.Fl P
 +option is useful combined with the
 +.Fl r
 +option as 
 +.Ar supervisor_pidfile
 +contains the ID of the supervisor
 +not the child. This is especially important if you use
 +.Fl r
 +in an rc script as the
 +.Fl p
 +option will give you the child's ID to signal when you attempt to
 +stop the service, causing 
 +.Nm
 +to restart the child.
  .Sh EXIT STATUS
  The
  .Nm
  utility exits 1 if an error is returned by the
  .Xr daemon 3
 -library routine, 2 if the
 -.Ar pidfile
 +library routine, 2 if
 +.Ar child_pidfile
 +or
 +.Ar supervisor_pidfile
  is requested, but cannot be opened, 3 if process is already running (pidfile
  exists and is locked),
  otherwise 0.
 Index: daemon.c
 ===================================================================
 --- daemon.c	(revision 255500)
 +++ daemon.c	(working copy)
 @@ -53,16 +53,17 @@ static void usage(void);
  int
  main(int argc, char *argv[])
  {
 -	struct pidfh *pfh = NULL;
 +	struct pidfh  *ppfh, *pfh;
  	sigset_t mask, oldmask;
  	int ch, nochdir, noclose, restart;
 -	const char *pidfile, *user;
 +	const char *pidfile, *ppidfile,  *user;
  	pid_t otherpid, pid;
  
  	nochdir = noclose = 1;
  	restart = 0;
 -	pidfile = user = NULL;
 -	while ((ch = getopt(argc, argv, "cfp:ru:")) != -1) {
 +	ppfh = pfh = NULL;
 +	ppidfile = pidfile = user = NULL;
 +	while ((ch = getopt(argc, argv, "cfp:P:ru:")) != -1) {
  		switch (ch) {
  		case 'c':
  			nochdir = 0;
 @@ -73,6 +74,9 @@ main(int argc, char *argv[])
  		case 'p':
  			pidfile = optarg;
  			break;
 +		case 'P':
 +			ppidfile = optarg;
 +			break;
  		case 'r':
  			restart = 1;
  			break;
 @@ -89,7 +93,7 @@ main(int argc, char *argv[])
  	if (argc == 0)
  		usage();
  
 -	pfh = NULL;
 +	ppfh = pfh = NULL;
  	/*
  	 * Try to open the pidfile before calling daemon(3),
  	 * to be able to report the error intelligently
 @@ -104,6 +108,18 @@ main(int argc, char *argv[])
  			err(2, "pidfile ``%s''", pidfile);
  		}
  	}
 +	
 +	/* do same for actual daemon process */
 +	if (ppidfile != NULL) {
 +		ppfh = pidfile_open(ppidfile, 0600, &otherpid);
 +		if (ppfh == NULL) {
 +			if (errno == EEXIST) {
 +				errx(3, "process already running, pid: %d",
 +				     otherpid);
 +			}
 +			err(2, "ppidfile ``%s''", ppidfile);
 +		}
 +	}
  
  	if (daemon(nochdir, noclose) == -1)
  		err(1, NULL);
 @@ -176,12 +192,17 @@ restart:
  		 */
  		err(1, "%s", argv[0]);
  	}
 +	/* write out parent pidfile if needed */
 +	if (ppidfile != NULL)
 +		pidfile_write(ppfh);
 +
  	setproctitle("%s[%d]", argv[0], pid);
  	if (wait_child(pid, &mask) == 0 && restart) {
  		sleep(1);
  		goto restart;
  	}
  	pidfile_remove(pfh);
 +	pidfile_remove(ppfh);
  	exit(0); /* Exit status does not matter. */
  }
  
 @@ -240,7 +261,7 @@ static void
  usage(void)
  {
  	(void)fprintf(stderr,
 -	    "usage: daemon [-cfr] [-p pidfile] [-u user] command "
 +	    "usage: daemon [-cfr] [-p child_pidfile] [-P supervisor_pidfile] [-u user] command "
  		"arguments ...\n");
  	exit(1);
  }
 
 --n/aVsWSeQ4JHkrmm--
State-Changed-From-To: open->patched 
State-Changed-By: jmg 
State-Changed-When: Fri Sep 13 16:57:48 UTC 2013 
State-Changed-Why:  
patch applied to head in r255521 w/ man page date bumped and usage lines 
wrapped better... 

http://www.freebsd.org/cgi/query-pr.cgi?pr=181341 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/181341: commit references a PR
Date: Fri, 13 Sep 2013 16:57:42 +0000 (UTC)

 Author: jmg
 Date: Fri Sep 13 16:57:28 2013
 New Revision: 255521
 URL: http://svnweb.freebsd.org/changeset/base/255521
 
 Log:
   add support for writing the pid of the daemon program to a pid file so
   that daemon can be used w/ rc.subr and ports can use the additional
   functionality, such as keeping the ldap daemon up and running, and have
   the proper program to signal to exit..
   
   PR:		bin/181341
   Submitted by:	feld
   Approved by:	re (glebius)
 
 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	Fri Sep 13 14:15:52 2013	(r255520)
 +++ head/usr.sbin/daemon/daemon.8	Fri Sep 13 16:57:28 2013	(r255521)
 @@ -26,7 +26,7 @@
  .\"
  .\" $FreeBSD$
  .\"
 -.Dd June 4, 2012
 +.Dd September 13, 2013
  .Dt DAEMON 8
  .Os
  .Sh NAME
 @@ -35,7 +35,8 @@
  .Sh SYNOPSIS
  .Nm
  .Op Fl cfr
 -.Op Fl p Ar pidfile
 +.Op Fl p Ar child_pidfile
 +.Op Fl P Ar supervisor_pidfile
  .Op Fl u Ar user
  .Ar command arguments ...
  .Sh DESCRIPTION
 @@ -53,19 +54,39 @@ Change the current working directory to 
  .It Fl f
  Redirect standard input, standard output and standard error to
  .Pa /dev/null .
 -.It Fl p Ar file
 +.It Fl p Ar child_pidfile
  Write the ID of the created process into the
 -.Ar file
 +.Ar child_pidfile
  using the
  .Xr pidfile 3
  functionality.
  The program is executed in a spawned child process while the
  .Nm
  waits until it terminates to keep the
 -.Ar file
 +.Ar child_pidfile
  locked and removes it after the process exits.
  The
 -.Ar file
 +.Ar child_pidfile
 +owner is the user who runs the
 +.Nm
 +regardless of whether the
 +.Fl u
 +option is used or not.
 +.It Fl P Ar supervisor_pidfile
 +Write the ID of the 
 +.Nm
 +process into the
 +.Ar supervisor_pidfile
 +using the
 +.Xr pidfile 3
 +functionality.
 +The program is executed in a spawned child process while the
 +.Nm
 +waits until it terminates to keep the
 +.Ar supervisor_pidfile
 +locked and removes it after the process exits.
 +The
 +.Ar supervisor_pidfile
  owner is the user who runs the
  .Nm
  regardless of whether the
 @@ -79,27 +100,46 @@ Requires adequate superuser privileges.
  .El
  .Pp
  If the
 -.Fl p
 +.Fl p ,
 +.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
 +waits until it terminates to keep the pid file(s) locked and removes them
  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.
 +Normally it will cause the child to exit, remove the pidfile(s)
 +and then terminate.
 +.Pp
 +The
 +.Fl P
 +option is useful combined with the
 +.Fl r
 +option as 
 +.Ar supervisor_pidfile
 +contains the ID of the supervisor
 +not the child. This is especially important if you use
 +.Fl r
 +in an rc script as the
 +.Fl p
 +option will give you the child's ID to signal when you attempt to
 +stop the service, causing 
 +.Nm
 +to restart the child.
  .Sh EXIT STATUS
  The
  .Nm
  utility exits 1 if an error is returned by the
  .Xr daemon 3
 -library routine, 2 if the
 -.Ar pidfile
 +library routine, 2 if
 +.Ar child_pidfile
 +or
 +.Ar supervisor_pidfile
  is requested, but cannot be opened, 3 if process is already running (pidfile
  exists and is locked),
  otherwise 0.
 
 Modified: head/usr.sbin/daemon/daemon.c
 ==============================================================================
 --- head/usr.sbin/daemon/daemon.c	Fri Sep 13 14:15:52 2013	(r255520)
 +++ head/usr.sbin/daemon/daemon.c	Fri Sep 13 16:57:28 2013	(r255521)
 @@ -53,16 +53,17 @@ static void usage(void);
  int
  main(int argc, char *argv[])
  {
 -	struct pidfh *pfh = NULL;
 +	struct pidfh  *ppfh, *pfh;
  	sigset_t mask, oldmask;
  	int ch, nochdir, noclose, restart;
 -	const char *pidfile, *user;
 +	const char *pidfile, *ppidfile,  *user;
  	pid_t otherpid, pid;
  
  	nochdir = noclose = 1;
  	restart = 0;
 -	pidfile = user = NULL;
 -	while ((ch = getopt(argc, argv, "cfp:ru:")) != -1) {
 +	ppfh = pfh = NULL;
 +	ppidfile = pidfile = user = NULL;
 +	while ((ch = getopt(argc, argv, "cfp:P:ru:")) != -1) {
  		switch (ch) {
  		case 'c':
  			nochdir = 0;
 @@ -73,6 +74,9 @@ main(int argc, char *argv[])
  		case 'p':
  			pidfile = optarg;
  			break;
 +		case 'P':
 +			ppidfile = optarg;
 +			break;
  		case 'r':
  			restart = 1;
  			break;
 @@ -89,7 +93,7 @@ main(int argc, char *argv[])
  	if (argc == 0)
  		usage();
  
 -	pfh = NULL;
 +	ppfh = pfh = NULL;
  	/*
  	 * Try to open the pidfile before calling daemon(3),
  	 * to be able to report the error intelligently
 @@ -104,6 +108,18 @@ main(int argc, char *argv[])
  			err(2, "pidfile ``%s''", pidfile);
  		}
  	}
 +	
 +	/* do same for actual daemon process */
 +	if (ppidfile != NULL) {
 +		ppfh = pidfile_open(ppidfile, 0600, &otherpid);
 +		if (ppfh == NULL) {
 +			if (errno == EEXIST) {
 +				errx(3, "process already running, pid: %d",
 +				     otherpid);
 +			}
 +			err(2, "ppidfile ``%s''", ppidfile);
 +		}
 +	}
  
  	if (daemon(nochdir, noclose) == -1)
  		err(1, NULL);
 @@ -176,12 +192,17 @@ restart:
  		 */
  		err(1, "%s", argv[0]);
  	}
 +	/* write out parent pidfile if needed */
 +	if (ppidfile != NULL)
 +		pidfile_write(ppfh);
 +
  	setproctitle("%s[%d]", argv[0], pid);
  	if (wait_child(pid, &mask) == 0 && restart) {
  		sleep(1);
  		goto restart;
  	}
  	pidfile_remove(pfh);
 +	pidfile_remove(ppfh);
  	exit(0); /* Exit status does not matter. */
  }
  
 @@ -240,7 +261,7 @@ static void
  usage(void)
  {
  	(void)fprintf(stderr,
 -	    "usage: daemon [-cfr] [-p pidfile] [-u user] command "
 -		"arguments ...\n");
 +	    "usage: daemon [-cfr] [-p child_pidfile] [-P supervisor_pidfile] "
 +	    "[-u user]\n              command arguments ...\n");
  	exit(1);
  }
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/181341: commit references a PR
Date: Thu,  3 Oct 2013 18:48:58 +0000 (UTC)

 Author: trociny
 Date: Thu Oct  3 18:48:43 2013
 New Revision: 256025
 URL: http://svnweb.freebsd.org/changeset/base/256025
 
 Log:
   MFC r255521, r255526, r255707:
   
   r255521 (jmg):
   
   add support for writing the pid of the daemon program to a pid file so
   that daemon can be used w/ rc.subr and ports can use the additional
   functionality, such as keeping the ldap daemon up and running, and have
   the proper program to signal to exit..
   
   PR:		bin/181341
   Submitted by:	feld
   
   r255526 (joel):
   
   mdoc: remove EOL whitespace.
   
   r255707:
   
   1. Properly clean pid files in the case of the error.
   2. Write the supervisor pid before the restart loop, so we don't
      uselessly rewrite it after every child restart.
   3. Remove duplicate ppfh and pfh initialization.
 
 Modified:
   stable/9/usr.sbin/daemon/daemon.8
   stable/9/usr.sbin/daemon/daemon.c
 Directory Properties:
   stable/9/usr.sbin/daemon/   (props changed)
 
 Modified: stable/9/usr.sbin/daemon/daemon.8
 ==============================================================================
 --- stable/9/usr.sbin/daemon/daemon.8	Thu Oct  3 17:50:14 2013	(r256024)
 +++ stable/9/usr.sbin/daemon/daemon.8	Thu Oct  3 18:48:43 2013	(r256025)
 @@ -26,7 +26,7 @@
  .\"
  .\" $FreeBSD$
  .\"
 -.Dd June 4, 2012
 +.Dd September 13, 2013
  .Dt DAEMON 8
  .Os
  .Sh NAME
 @@ -35,7 +35,8 @@
  .Sh SYNOPSIS
  .Nm
  .Op Fl cfr
 -.Op Fl p Ar pidfile
 +.Op Fl p Ar child_pidfile
 +.Op Fl P Ar supervisor_pidfile
  .Op Fl u Ar user
  .Ar command arguments ...
  .Sh DESCRIPTION
 @@ -53,19 +54,39 @@ Change the current working directory to 
  .It Fl f
  Redirect standard input, standard output and standard error to
  .Pa /dev/null .
 -.It Fl p Ar file
 +.It Fl p Ar child_pidfile
  Write the ID of the created process into the
 -.Ar file
 +.Ar child_pidfile
  using the
  .Xr pidfile 3
  functionality.
  The program is executed in a spawned child process while the
  .Nm
  waits until it terminates to keep the
 -.Ar file
 +.Ar child_pidfile
  locked and removes it after the process exits.
  The
 -.Ar file
 +.Ar child_pidfile
 +owner is the user who runs the
 +.Nm
 +regardless of whether the
 +.Fl u
 +option is used or not.
 +.It Fl P Ar supervisor_pidfile
 +Write the ID of the
 +.Nm
 +process into the
 +.Ar supervisor_pidfile
 +using the
 +.Xr pidfile 3
 +functionality.
 +The program is executed in a spawned child process while the
 +.Nm
 +waits until it terminates to keep the
 +.Ar supervisor_pidfile
 +locked and removes it after the process exits.
 +The
 +.Ar supervisor_pidfile
  owner is the user who runs the
  .Nm
  regardless of whether the
 @@ -79,27 +100,46 @@ Requires adequate superuser privileges.
  .El
  .Pp
  If the
 -.Fl p
 +.Fl p ,
 +.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
 +waits until it terminates to keep the pid file(s) locked and removes them
  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.
 +Normally it will cause the child to exit, remove the pidfile(s)
 +and then terminate.
 +.Pp
 +The
 +.Fl P
 +option is useful combined with the
 +.Fl r
 +option as
 +.Ar supervisor_pidfile
 +contains the ID of the supervisor
 +not the child. This is especially important if you use
 +.Fl r
 +in an rc script as the
 +.Fl p
 +option will give you the child's ID to signal when you attempt to
 +stop the service, causing
 +.Nm
 +to restart the child.
  .Sh EXIT STATUS
  The
  .Nm
  utility exits 1 if an error is returned by the
  .Xr daemon 3
 -library routine, 2 if the
 -.Ar pidfile
 +library routine, 2 if
 +.Ar child_pidfile
 +or
 +.Ar supervisor_pidfile
  is requested, but cannot be opened, 3 if process is already running (pidfile
  exists and is locked),
  otherwise 0.
 
 Modified: stable/9/usr.sbin/daemon/daemon.c
 ==============================================================================
 --- stable/9/usr.sbin/daemon/daemon.c	Thu Oct  3 17:50:14 2013	(r256024)
 +++ stable/9/usr.sbin/daemon/daemon.c	Thu Oct  3 18:48:43 2013	(r256025)
 @@ -53,16 +53,16 @@ static void usage(void);
  int
  main(int argc, char *argv[])
  {
 -	struct pidfh *pfh = NULL;
 +	struct pidfh  *ppfh, *pfh;
  	sigset_t mask, oldmask;
 -	int ch, nochdir, noclose, restart;
 -	const char *pidfile, *user;
 +	int ch, nochdir, noclose, restart, serrno;
 +	const char *pidfile, *ppidfile,  *user;
  	pid_t otherpid, pid;
  
  	nochdir = noclose = 1;
  	restart = 0;
 -	pidfile = user = NULL;
 -	while ((ch = getopt(argc, argv, "cfp:ru:")) != -1) {
 +	ppidfile = pidfile = user = NULL;
 +	while ((ch = getopt(argc, argv, "cfp:P:ru:")) != -1) {
  		switch (ch) {
  		case 'c':
  			nochdir = 0;
 @@ -73,6 +73,9 @@ main(int argc, char *argv[])
  		case 'p':
  			pidfile = optarg;
  			break;
 +		case 'P':
 +			ppidfile = optarg;
 +			break;
  		case 'r':
  			restart = 1;
  			break;
 @@ -89,7 +92,7 @@ main(int argc, char *argv[])
  	if (argc == 0)
  		usage();
  
 -	pfh = NULL;
 +	ppfh = pfh = NULL;
  	/*
  	 * Try to open the pidfile before calling daemon(3),
  	 * to be able to report the error intelligently
 @@ -104,9 +107,27 @@ main(int argc, char *argv[])
  			err(2, "pidfile ``%s''", pidfile);
  		}
  	}
 +	/* Do the same for actual daemon process. */
 +	if (ppidfile != NULL) {
 +		ppfh = pidfile_open(ppidfile, 0600, &otherpid);
 +		if (ppfh == NULL) {
 +			serrno = errno;
 +			pidfile_remove(pfh);
 +			errno = serrno;
 +			if (errno == EEXIST) {
 +				errx(3, "process already running, pid: %d",
 +				     otherpid);
 +			}
 +			err(2, "ppidfile ``%s''", ppidfile);
 +		}
 +	}
  
 -	if (daemon(nochdir, noclose) == -1)
 -		err(1, NULL);
 +	if (daemon(nochdir, noclose) == -1) {
 +		warn("daemon");
 +		goto exit;
 +	}
 +	/* Write out parent pidfile if needed. */
 +	pidfile_write(ppfh);
  
  	/*
  	 * If the pidfile or restart option is specified the daemon
 @@ -123,22 +144,28 @@ main(int argc, char *argv[])
  		 * Restore default action for SIGTERM in case the
  		 * parent process decided to ignore it.
  		 */
 -		if (signal(SIGTERM, SIG_DFL) == SIG_ERR)
 -			err(1, "signal");
 +		if (signal(SIGTERM, SIG_DFL) == SIG_ERR) {
 +			warn("signal");
 +			goto exit;
 +		}
  		/*
  		 * Because SIGCHLD is ignored by default, setup dummy handler
  		 * for it, so we can mask it.
  		 */
 -		if (signal(SIGCHLD, dummy_sighandler) == SIG_ERR)
 -			err(1, "signal");
 +		if (signal(SIGCHLD, dummy_sighandler) == SIG_ERR) {
 +			warn("signal");
 +			goto exit;
 +		}
  		/*
  		 * Block interesting signals.
  		 */
  		sigemptyset(&mask);
  		sigaddset(&mask, SIGTERM);
  		sigaddset(&mask, SIGCHLD);
 -		if (sigprocmask(SIG_SETMASK, &mask, &oldmask) == -1)
 -			err(1, "sigprocmask");
 +		if (sigprocmask(SIG_SETMASK, &mask, &oldmask) == -1) {
 +			warn("sigprocmask");
 +			goto exit;
 +		}
  		/*
  		 * Try to protect against pageout kill. Ignore the
  		 * error, madvise(2) will fail only if a process does
 @@ -152,8 +179,8 @@ restart:
  		 */
  		pid = fork();
  		if (pid == -1) {
 -			pidfile_remove(pfh);
 -			err(1, "fork");
 +			warn("fork");
 +			goto exit;
  		}
  	}
  	if (pid <= 0) {
 @@ -176,13 +203,16 @@ restart:
  		 */
  		err(1, "%s", argv[0]);
  	}
 +
  	setproctitle("%s[%d]", argv[0], pid);
  	if (wait_child(pid, &mask) == 0 && restart) {
  		sleep(1);
  		goto restart;
  	}
 +exit:
  	pidfile_remove(pfh);
 -	exit(0); /* Exit status does not matter. */
 +	pidfile_remove(ppfh);
 +	exit(1); /* If daemon(3) succeeded exit status does not matter. */
  }
  
  static void
 @@ -240,7 +270,7 @@ static void
  usage(void)
  {
  	(void)fprintf(stderr,
 -	    "usage: daemon [-cfr] [-p pidfile] [-u user] command "
 -		"arguments ...\n");
 +	    "usage: daemon [-cfr] [-p child_pidfile] [-P supervisor_pidfile] "
 +	    "[-u user]\n              command arguments ...\n");
  	exit(1);
  }
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/181341: commit references a PR
Date: Thu,  3 Oct 2013 18:50:17 +0000 (UTC)

 Author: trociny
 Date: Thu Oct  3 18:50:09 2013
 New Revision: 256026
 URL: http://svnweb.freebsd.org/changeset/base/256026
 
 Log:
   MFC r255521, r255526, r255707:
   
   r255521 (jmg):
   
   add support for writing the pid of the daemon program to a pid file so
   that daemon can be used w/ rc.subr and ports can use the additional
   functionality, such as keeping the ldap daemon up and running, and have
   the proper program to signal to exit.
   
   PR:		bin/181341
   Submitted by:	feld
   
   r255526 (joel):
   
   mdoc: remove EOL whitespace.
   
   r255707:
   
   1. Properly clean pid files in the case of the error.
   2. Write the supervisor pid before the restart loop, so we don't
      uselessly rewrite it after every child restart.
   3. Remove duplicate ppfh and pfh initialization.
 
 Modified:
   stable/8/usr.sbin/daemon/daemon.8
   stable/8/usr.sbin/daemon/daemon.c
 Directory Properties:
   stable/8/usr.sbin/daemon/   (props changed)
 
 Modified: stable/8/usr.sbin/daemon/daemon.8
 ==============================================================================
 --- stable/8/usr.sbin/daemon/daemon.8	Thu Oct  3 18:48:43 2013	(r256025)
 +++ stable/8/usr.sbin/daemon/daemon.8	Thu Oct  3 18:50:09 2013	(r256026)
 @@ -26,7 +26,7 @@
  .\"
  .\" $FreeBSD$
  .\"
 -.Dd June 4, 2012
 +.Dd September 13, 2013
  .Dt DAEMON 8
  .Os
  .Sh NAME
 @@ -35,7 +35,8 @@
  .Sh SYNOPSIS
  .Nm
  .Op Fl cfr
 -.Op Fl p Ar pidfile
 +.Op Fl p Ar child_pidfile
 +.Op Fl P Ar supervisor_pidfile
  .Op Fl u Ar user
  .Ar command arguments ...
  .Sh DESCRIPTION
 @@ -53,19 +54,39 @@ Change the current working directory to 
  .It Fl f
  Redirect standard input, standard output and standard error to
  .Pa /dev/null .
 -.It Fl p Ar file
 +.It Fl p Ar child_pidfile
  Write the ID of the created process into the
 -.Ar file
 +.Ar child_pidfile
  using the
  .Xr pidfile 3
  functionality.
  The program is executed in a spawned child process while the
  .Nm
  waits until it terminates to keep the
 -.Ar file
 +.Ar child_pidfile
  locked and removes it after the process exits.
  The
 -.Ar file
 +.Ar child_pidfile
 +owner is the user who runs the
 +.Nm
 +regardless of whether the
 +.Fl u
 +option is used or not.
 +.It Fl P Ar supervisor_pidfile
 +Write the ID of the
 +.Nm
 +process into the
 +.Ar supervisor_pidfile
 +using the
 +.Xr pidfile 3
 +functionality.
 +The program is executed in a spawned child process while the
 +.Nm
 +waits until it terminates to keep the
 +.Ar supervisor_pidfile
 +locked and removes it after the process exits.
 +The
 +.Ar supervisor_pidfile
  owner is the user who runs the
  .Nm
  regardless of whether the
 @@ -79,27 +100,46 @@ Requires adequate superuser privileges.
  .El
  .Pp
  If the
 -.Fl p
 +.Fl p ,
 +.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
 +waits until it terminates to keep the pid file(s) locked and removes them
  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.
 +Normally it will cause the child to exit, remove the pidfile(s)
 +and then terminate.
 +.Pp
 +The
 +.Fl P
 +option is useful combined with the
 +.Fl r
 +option as
 +.Ar supervisor_pidfile
 +contains the ID of the supervisor
 +not the child. This is especially important if you use
 +.Fl r
 +in an rc script as the
 +.Fl p
 +option will give you the child's ID to signal when you attempt to
 +stop the service, causing
 +.Nm
 +to restart the child.
  .Sh EXIT STATUS
  The
  .Nm
  utility exits 1 if an error is returned by the
  .Xr daemon 3
 -library routine, 2 if the
 -.Ar pidfile
 +library routine, 2 if
 +.Ar child_pidfile
 +or
 +.Ar supervisor_pidfile
  is requested, but cannot be opened, 3 if process is already running (pidfile
  exists and is locked),
  otherwise 0.
 
 Modified: stable/8/usr.sbin/daemon/daemon.c
 ==============================================================================
 --- stable/8/usr.sbin/daemon/daemon.c	Thu Oct  3 18:48:43 2013	(r256025)
 +++ stable/8/usr.sbin/daemon/daemon.c	Thu Oct  3 18:50:09 2013	(r256026)
 @@ -53,16 +53,16 @@ static void usage(void);
  int
  main(int argc, char *argv[])
  {
 -	struct pidfh *pfh = NULL;
 +	struct pidfh  *ppfh, *pfh;
  	sigset_t mask, oldmask;
 -	int ch, nochdir, noclose, restart;
 -	const char *pidfile, *user;
 +	int ch, nochdir, noclose, restart, serrno;
 +	const char *pidfile, *ppidfile,  *user;
  	pid_t otherpid, pid;
  
  	nochdir = noclose = 1;
  	restart = 0;
 -	pidfile = user = NULL;
 -	while ((ch = getopt(argc, argv, "cfp:ru:")) != -1) {
 +	ppidfile = pidfile = user = NULL;
 +	while ((ch = getopt(argc, argv, "cfp:P:ru:")) != -1) {
  		switch (ch) {
  		case 'c':
  			nochdir = 0;
 @@ -73,6 +73,9 @@ main(int argc, char *argv[])
  		case 'p':
  			pidfile = optarg;
  			break;
 +		case 'P':
 +			ppidfile = optarg;
 +			break;
  		case 'r':
  			restart = 1;
  			break;
 @@ -89,7 +92,7 @@ main(int argc, char *argv[])
  	if (argc == 0)
  		usage();
  
 -	pfh = NULL;
 +	ppfh = pfh = NULL;
  	/*
  	 * Try to open the pidfile before calling daemon(3),
  	 * to be able to report the error intelligently
 @@ -104,9 +107,27 @@ main(int argc, char *argv[])
  			err(2, "pidfile ``%s''", pidfile);
  		}
  	}
 +	/* Do the same for actual daemon process. */
 +	if (ppidfile != NULL) {
 +		ppfh = pidfile_open(ppidfile, 0600, &otherpid);
 +		if (ppfh == NULL) {
 +			serrno = errno;
 +			pidfile_remove(pfh);
 +			errno = serrno;
 +			if (errno == EEXIST) {
 +				errx(3, "process already running, pid: %d",
 +				     otherpid);
 +			}
 +			err(2, "ppidfile ``%s''", ppidfile);
 +		}
 +	}
  
 -	if (daemon(nochdir, noclose) == -1)
 -		err(1, NULL);
 +	if (daemon(nochdir, noclose) == -1) {
 +		warn("daemon");
 +		goto exit;
 +	}
 +	/* Write out parent pidfile if needed. */
 +	pidfile_write(ppfh);
  
  	/*
  	 * If the pidfile or restart option is specified the daemon
 @@ -123,22 +144,28 @@ main(int argc, char *argv[])
  		 * Restore default action for SIGTERM in case the
  		 * parent process decided to ignore it.
  		 */
 -		if (signal(SIGTERM, SIG_DFL) == SIG_ERR)
 -			err(1, "signal");
 +		if (signal(SIGTERM, SIG_DFL) == SIG_ERR) {
 +			warn("signal");
 +			goto exit;
 +		}
  		/*
  		 * Because SIGCHLD is ignored by default, setup dummy handler
  		 * for it, so we can mask it.
  		 */
 -		if (signal(SIGCHLD, dummy_sighandler) == SIG_ERR)
 -			err(1, "signal");
 +		if (signal(SIGCHLD, dummy_sighandler) == SIG_ERR) {
 +			warn("signal");
 +			goto exit;
 +		}
  		/*
  		 * Block interesting signals.
  		 */
  		sigemptyset(&mask);
  		sigaddset(&mask, SIGTERM);
  		sigaddset(&mask, SIGCHLD);
 -		if (sigprocmask(SIG_SETMASK, &mask, &oldmask) == -1)
 -			err(1, "sigprocmask");
 +		if (sigprocmask(SIG_SETMASK, &mask, &oldmask) == -1) {
 +			warn("sigprocmask");
 +			goto exit;
 +		}
  		/*
  		 * Try to protect against pageout kill. Ignore the
  		 * error, madvise(2) will fail only if a process does
 @@ -152,8 +179,8 @@ restart:
  		 */
  		pid = fork();
  		if (pid == -1) {
 -			pidfile_remove(pfh);
 -			err(1, "fork");
 +			warn("fork");
 +			goto exit;
  		}
  	}
  	if (pid <= 0) {
 @@ -176,13 +203,16 @@ restart:
  		 */
  		err(1, "%s", argv[0]);
  	}
 +
  	setproctitle("%s[%d]", argv[0], pid);
  	if (wait_child(pid, &mask) == 0 && restart) {
  		sleep(1);
  		goto restart;
  	}
 +exit:
  	pidfile_remove(pfh);
 -	exit(0); /* Exit status does not matter. */
 +	pidfile_remove(ppfh);
 +	exit(1); /* If daemon(3) succeeded exit status does not matter. */
  }
  
  static void
 @@ -240,7 +270,7 @@ static void
  usage(void)
  {
  	(void)fprintf(stderr,
 -	    "usage: daemon [-cfr] [-p pidfile] [-u user] command "
 -		"arguments ...\n");
 +	    "usage: daemon [-cfr] [-p child_pidfile] [-P supervisor_pidfile] "
 +	    "[-u user]\n              command arguments ...\n");
  	exit(1);
  }
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: patched->closed 
State-Changed-By: jmg 
State-Changed-When: Thu Oct 3 19:08:57 UTC 2013 
State-Changed-Why:  
patch back port to stable/8 and stable/9 plus additional fixes.. 

Thanks Mikolaj... 

http://www.freebsd.org/cgi/query-pr.cgi?pr=181341 
>Unformatted:
