Jos Backus <[EMAIL PROTECTED]> writes: > OK, so we only fork if we are a pgrp leader. Since whether or not to fork is > the only thing NO_DETACH controls and since this decision is now to be based > on the process' pgrp leader status, it seems that NO_DETACH has become > obsolete as we can determine this automatically: when httpd is run by the > shell, it's a pgrp leader so we fork; if run by a process controller, it's not > a pgrp leader so we don't fork.
This assumption is dangerous and incorrect. You're overlooking the interaction between sessions, process groups, and shells with and without job control. httpd calls setsid(2) not only to create a new process group and become its leader, but to escape the current session and controlling terminal. setsid(2) has to be called regardless of whether we want the main httpd to double-fork away from its parent, to get away from the controlling terminal. You can't call setsid(2) if you're already process group leader. However, when you invoke httpd under a shell with job control (e.g. bash), it is automatically put into a new process group as the leader: Starting under Solaris /bin/sh without job control: # ps -o uid,pid,ppid,pgid,sid,comm UID PID PPID PGID SID COMMAND 0 20240 20238 20240 20240 -sh 0 20255 20240 20240 20240 ps # ./test pid = 20256, pgrp = 20240, sid = 20240 We're a member of the parent shell's process group, but not the leader, and thus can setsid(2). Starting under bash with job control: # bash root@build1:~# ps -o uid,pid,ppid,pgid,sid,comm UID PID PPID PGID SID COMMAND 0 20251 20250 20251 20240 ps 0 20240 20238 20240 20240 -sh 0 20250 20240 20250 20240 bash root@build1:~# ./test pid = 20252, pgrp = 20252, sid = 20240 We're a member of our OWN process group AND the leader, and thus can't setsid(2). This is the reason that httpd forks before calling setsid(2) -- so that in case it was run under a shell with job control and was made process group leader, it's not process group leader anymore, because its parent is, or rather was, before it exited). [1] Thus, if httpd is started from a shell with job control, it MUST fork(2) at least once before calling setsid(2). Note that this means that our non-forking process supervisor mode for httpd will never work if httpd is invoked from a shell with job control. I think this is a reasonable restriction, as long as it's properly noted in the documentation. Now, Jos' assumption above is dangerous because if you're invoked from a system startup script that runs under a shell without job control, e.g. Solaris /bin/sh, you're not going to be process group leader. Under the logic above, it wouldn't daemonize, and the system startup script would never exit, and system startup would hang forever. (Hope you started sshd before httpd. :)) I don't believe that there's any portable or reliable way for httpd to detect whether whether it's being run under a 'process controller' or not. As I've just shown above, whether it's a process group leader already is not reliable. Thus, we need to make httpd have a normal mode (daemonize), with a command line switch to disable this behavior (-DWHATEVER) if a sysadmin wants to run httpd under a process controller. I also wouldn't mind if someone took a look at my patch for apache 1.3.22 to accomplish this same issue. :) http://bugs.apache.org/index.cgi/full/9341 Thanks for your consideration. --michael [1] Stevens, _Unix Network Programming, Volume One_ (2nd Edition), pp 335: "We first call fork(2) and then the parent terminates and the child continues. [...] Also, the child inherits the process group ID from the parent but gets its own process ID. This guarantees that the child is not a process group leader, which is required for the next call to setsid(2)." -- [EMAIL PROTECTED] (michael handler) washington, dc