[comp.unix.questions] Starting a daemon on a SVR3

wolf@grasp1.univ-lyon1.fr (Christophe Wolfhugel) (12/31/90)

On an old AIX, I use following code to start a daemon (which does not run
with root privileges).

   setbuf(stdout,NULL); printf("Listserv v0.99: daemon started\n\r");
   if (fork()) exit (0);   /* Dissociate us from tty */
   for (i=getdtablesize()-1; i>=0; i--)
      (void)close(i);
   (void)open("/",0);
   (void)dup2(0,1);
   (void)dup2(0,2);
   i=open("/dev/tty",2);
   if (i>=0) {
      ioctl(i,TIOCNOTTY,(char *)0);
      (void)close(i);
   }

This works fine, but I get trouble when porting this daemon to an SRV3.
getdtablesize does not exist anymore, so I close all open files manually
with a fixed loop (I put 4 in first index).

The ioctl call does also not exist, and I found no equivalence.
After having executed the new code it loads itself in background and
ps shows me it does not depend anymore on a tty.  Despite this, when
I loggoff, the process is being killed.  Can anyone explain me what I
have to do to start properly a daemon?  Thanx.

-- 
Christophe Wolfhugel                  |  Email: wolf@grasp1.univ-lyon1.fr
INSA Lyon - Departement Informatique  |  Fax: (+33) 72 44 08 00 
69621 Villeurbanne Cedex, France      |    (Attn-To: Wolfhugel - C 210)

  Disclaimer: these are my own opinions, not my employer's.

les@chinet.chi.il.us (Leslie Mikesell) (01/01/91)

In article <25360@adm.brl.mil> wolf@grasp1.univ-lyon1.fr writes:
>On an old AIX, I use following code to start a daemon (which does not run
>with root privileges).

>      ioctl(i,TIOCNOTTY,(char *)0);

>The ioctl call does also not exist, and I found no equivalence.
>After having executed the new code it loads itself in background and
>ps shows me it does not depend anymore on a tty.  Despite this, when
>I loggoff, the process is being killed.

You need setpgrp() to disassociate from the inherited process group.
The next tty the process opens becomes the controlling terminal for
the new process group, so you may have to watch out for unexpected
signals.

Les Mikesell
  les@chinet.chi.il.us

jky@neptune.dsc.com (Jacob Kan Yu) (01/03/91)

wolf@grasp1.univ-lyon1.fr writes:

>On an old AIX, I use following code to start a daemon (which does not run
>with root privileges).

>   setbuf(stdout,NULL); printf("Listserv v0.99: daemon started\n\r");
>   if (fork()) exit (0);   /* Dissociate us from tty */
>   for (i=getdtablesize()-1; i>=0; i--)
>      (void)close(i);
>   (void)open("/",0);
>   (void)dup2(0,1);
>   (void)dup2(0,2);
>   i=open("/dev/tty",2);
>   if (i>=0) {
>      ioctl(i,TIOCNOTTY,(char *)0);
>      (void)close(i);
>   }

>This works fine, but I get trouble when porting this daemon to an SRV3.
>getdtablesize does not exist anymore, so I close all open files manually
>with a fixed loop (I put 4 in first index).

What's about this:

    for ( i = 0 ; i < NOFILE ; i++ )
	close( i );

The problem I have is that "NOFILE" is 20 for System V/386 Release 3.0 and is
60 for Release 3.2 and the comments in "<sys/param.h>" says this number is
no longer a constant and should be removed in the next release.  Anybody
have better idea?

>The ioctl call does also not exist, and I found no equivalence.
>After having executed the new code it loads itself in background and
>ps shows me it does not depend anymore on a tty.  Despite this, when
>I loggoff, the process is being killed.  Can anyone explain me what I
>have to do to start properly a daemon?  Thanx.

I am not sure about this ioctl call but you probably should have your
program to ignore "SIGHUP" signal.

>-- 
>Christophe Wolfhugel                  |  Email: wolf@grasp1.univ-lyon1.fr
>INSA Lyon - Departement Informatique  |  Fax: (+33) 72 44 08 00 
>69621 Villeurbanne Cedex, France      |    (Attn-To: Wolfhugel - C 210)

Jacob Yu 	Internet: jky%neptune%dschub@hub.ucsb.edu
		Uucp:     pyramid!ucsbcsl!dschub!neptune!jky

Life is but a walking shadow.

>  Disclaimer: these are my own opinions, not my employer's.

Yes, these are my own opinions too.

src@scuzzy.in-berlin.de (Heiko Blume) (01/03/91)

jky@neptune.dsc.com (Jacob Kan Yu) writes:
>What's about this:

>    for ( i = 0 ; i < NOFILE ; i++ )
>	close( i );

>The problem I have is that "NOFILE" is 20 for System V/386 Release 3.0 and is
>60 for Release 3.2 and the comments in "<sys/param.h>" says this number is
>no longer a constant and should be removed in the next release.  Anybody
>have better idea?

yes [if you have posix stuff]:

    for ( i = 0 ; i < sysconf(_SC_OPEN_MAX) ; i++ )
	close( i );
-- 
      Heiko Blume <-+-> src@scuzzy.in-berlin.de <-+-> (+49 30) 691 88 93
                    public source archive [HST V.42bis]:
        scuzzy Any ACU,f 38400 6919520 gin:--gin: nuucp sword: nuucp
                     uucp scuzzy!/src/README /your/home

jim@segue.segue.com (Jim Balter) (01/04/91)

In article <1752@dschub.dsc.com> jky@neptune.dsc.com (Jacob Kan Yu) writes:
|What's about this:
|
|    for ( i = 0 ; i < NOFILE ; i++ )
|	close( i );
|
|The problem I have is that "NOFILE" is 20 for System V/386 Release 3.0 and is
|60 for Release 3.2 and the comments in "<sys/param.h>" says this number is
|no longer a constant and should be removed in the next release.  Anybody
|have better idea?

	/* assuming fd 0 is known to be open */

	while ( dup(0) == 0 );
	/* for ( i = 0; close(i++) == 0; ); */
	/* guard against NFS brain damage */
	for ( i = 0; close(i++) == 0 || errno != EBADF; );

mike@bria.AIX (Mike Stefanik/78125) (01/04/91)

In article <1991Jan03.132149.3565@scuzzy.in-berlin.de> src@scuzzy.in-berlin.de (Heiko Blume) writes:
[question about closing all open file descriptors]
>yes [if you have posix stuff]:
>
>    for ( i = 0 ; i < sysconf(_SC_OPEN_MAX) ; i++ )
>	close( i );

Since file descriptors are guaranteed to be assigned sequentially; whynot
simply do:

	i=0;
	while ( close(i++) != -1 )
		;

This would work without any soon-to-be-defunct #define's, and any gee-what-
is-POSIX libraries.  Just a thought.

-----------------------------------------------------------------------------
Michael Stefanik, Systems Engineer (JOAT), Briareus Corporation
UUCP: ...!uunet!bria!mike
"If it was hard to code, it should be harder to use!"

night@itsgw.rpi.edu (Trip Martin) (01/04/91)

mike@bria.AIX (Mike Stefanik/78125) writes:

>In article <1991Jan03.132149.3565@scuzzy.in-berlin.de> src@scuzzy.in-berlin.de (Heiko Blume) writes:
>[question about closing all open file descriptors]
>>yes [if you have posix stuff]:

>Since file descriptors are guaranteed to be assigned sequentially; whynot
>simply do:

>	i=0;
>	while ( close(i++) != -1 )
>		;

This won't work because there's nothing stopping the program from closing
file descriptors.  As an example, suppose the process had open file
descriptors 0 through 7, and then closed 3.  This code would leave open
4 through 7.

-- 
Trip Martin  
night@rpi.edu
-- 
Trip Martin  
night@rpi.edu

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (01/05/91)

In article <1991Jan03.132149.3565@scuzzy.in-berlin.de> src@scuzzy.in-berlin.de (Heiko Blume) writes:
>     for ( i = 0 ; i < sysconf(_SC_OPEN_MAX) ; i++ )
> 	close( i );

i = sysconf(_SC_OPEN_MAX);
while(i)
  close(--i);

There's no reason to be unnecessarily inefficient (or verbose), or to
clog trace logs.

---Dan

src@scuzzy.in-berlin.de (Heiko Blume) (01/06/91)

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) writes:

>>In article <1991Jan03.132149.3565@scuzzy.in-berlin.de> I wrote:
>>[inefficient code]

>[efficient code]
>There's no reason to be unnecessarily inefficient (or verbose), or to
>clog trace logs.

i must confess that i was real lazy, yanked the original code
and inserted the sysconf call :-) won't happen again!
-- 
      Heiko Blume <-+-> src@scuzzy.in-berlin.de <-+-> (+49 30) 691 88 93
                    public source archive [HST V.42bis]:
        scuzzy Any ACU,f 38400 6919520 gin:--gin: nuucp sword: nuucp
                     uucp scuzzy!/src/README /your/home

prc@erbe.se (Robert Claeson) (01/07/91)

In article <25360@adm.brl.mil> wolf@grasp1.univ-lyon1.fr writes:

>On an old AIX, I use following code to start a daemon (which does not run
>with root privileges).

[Source code deleted.]

>   setbuf(stdout,NULL); printf("Listserv v0.99: daemon started\n\r");
>   if (fork()) exit (0);   /* Dissociate us from tty */
>   for (i=getdtablesize()-1; i>=0; i--)
>      (void)close(i);
>   (void)open("/",0);
>   (void)dup2(0,1);
>   (void)dup2(0,2);
>   i=open("/dev/tty",2);
>   if (i>=0) {
>      ioctl(i,TIOCNOTTY,(char *)0);
>      (void)close(i);
>   }

>This works fine, but I get trouble when porting this daemon to an SRV3.
>getdtablesize does not exist anymore, so I close all open files manually
>with a fixed loop (I put 4 in first index).

>The ioctl call does also not exist, and I found no equivalence.
>After having executed the new code it loads itself in background and
>ps shows me it does not depend anymore on a tty.  Despite this, when
>I loggoff, the process is being killed.  Can anyone explain me what I
>have to do to start properly a daemon?  Thanx.

I believe that something along these lines should work:

	setbuf(stdout,NULL);
	printf("Listserv v0.99: daemon started\n\r");
	if (fork())		/* Disaccociate us from controlling tty */
		exit(0);
	setpgrp();		/* Start a new process group */
	if (fork())		/* ...and disaccociate us again */
		exit(0);

I only have a vague memory of why the second fork() is needed.

-- 
Robert Claeson                  |Reasonable mailers: rclaeson@erbe.se
ERBE DATA AB                    |      Dumb mailers: rclaeson%erbe.se@sunet.se
Jakobsberg, Sweden              |  Perverse mailers: rclaeson%erbe.se@encore.com
Any opinions expressed herein definitely belongs to me and not to my employer.

prc@erbe.se (Robert Claeson) (01/07/91)

In article <1991Jan03.132149.3565@scuzzy.in-berlin.de> src@scuzzy.in-berlin.de (Heiko Blume) writes:

>yes [if you have posix stuff]:
>
>    for ( i = 0 ; i < sysconf(_SC_OPEN_MAX) ; i++ )
>	close( i );

But is it really nessecary to close all files in order to create a daemon
under System V? I haven't done it, and yet everything seems to work as
it should.

-- 
Robert Claeson                  |Reasonable mailers: rclaeson@erbe.se
ERBE DATA AB                    |      Dumb mailers: rclaeson%erbe.se@sunet.se
Jakobsberg, Sweden              |  Perverse mailers: rclaeson%erbe.se@encore.com
Any opinions expressed herein definitely belongs to me and not to my employer.

src@scuzzy.in-berlin.de (Heiko Blume) (01/08/91)

prc@erbe.se (Robert Claeson) writes:

>In article <1991Jan03.132149.3565@scuzzy.in-berlin.de> I wrote:
>>[close()ing all fd's]

>But is it really nessecary to close all files in order to create a daemon
>under System V? I haven't done it, and yet everything seems to work as
>it should.

no, it's necessary to close all file descriptors that refer to the tty
that the daemon is started from, *plus* calling setpgrp(),
so that it runs independant.
(or, better said, all ttys that you don't want to get endangered)
that way you avoid getting SIGHUP etc., don't keep init from
respawning getty on ports with modem control, etc pepe.
to ensure that, you just close everything.

the following works on my sys v box (isc 2.2.1), it's called
in the child after a successul fork():


/*
 * generic function to make a daemon out of a simple fork()ed process.
 * however, if the daemon open()s a tty later it will be associated with 
 * that tty thereafter, even if a close() is issued. 
 */

void daemonize() {
	int fds=sysconf(_SC_OPEN_MAX); /* posixish */
	while(fds)
		(void) close(--fds);	/* close ALL file descriptors */
	setpgrp();					/* disassociate from terminal */
	sigset(SIGHUP,SIG_IGN)
	sigset(SIGINT,SIG_IGN);
	sigset(SIGQUIT,SIG_IGN);	/* don't disturb me */
	/* etc */
}

if you want to use redirection from/to regular files with your
daemon you should use

[...]
while(fds)
	if(isatty(--fds)) (void) close(fds);
[...]

thereby closing only file desriptors that are associated with a terminal
device.
-- 
      Heiko Blume <-+-> src@scuzzy.in-berlin.de <-+-> (+49 30) 691 88 93
                    public source archive [HST V.42bis]:
        scuzzy Any ACU,f 38400 6919520 gin:--gin: nuucp sword: nuucp
                     uucp scuzzy!/src/README /your/home

scjones@thor.UUCP (Larry Jones) (01/09/91)

In article <1991Jan7.120329.787@erbe.se>, prc@erbe.se (Robert Claeson) writes:
> I believe that something along these lines should work:
> 
> 	setbuf(stdout,NULL);
> 	printf("Listserv v0.99: daemon started\n\r");
> 	if (fork())		/* Disaccociate us from controlling tty */
> 		exit(0);
> 	setpgrp();		/* Start a new process group */
> 	if (fork())		/* ...and disaccociate us again */
> 		exit(0);
> 
> I only have a vague memory of why the second fork() is needed.

The reason for the second fork is to make sure that you don't get a
controlling terminal.  What happens is the first fork creates a new
process and the setpgrp then causes it to become a process group
leader.  This has the side-effect of disassociating it from its
controlling terminal, since controll tty is a process group related
thing.  The potential problem is that any time a process group
leader without a controlling tty opens a terminal that isn't
already open by someone else, it magically becomes the controlling
tty for that process group.  By forking again, you get rid of the
process group leader and don't have to worry about that happening.
----
Larry Jones                         UUCP: uunet!sdrc!thor!scjones
SDRC                                      scjones@thor.UUCP
2000 Eastman Dr.                    BIX:  ltl
Milford, OH  45150-2789             AT&T: (513) 576-2070
Do you think God lets you plea bargain? -- Calvin