This is part of The Pile, a partial archive of some open source mailing lists and newsgroups.
To: modperl <modperl@apache.org> From: Kees Vonk 7249 24549 <KEES.VONK@uktransco.com> Subject: fork inherits socket connection Date: Thu, 14 Dec 2000 15:36:26 +0000 (GMT) On our intranet server I have a page that allows the user to start a long running process. In order not to hang a httpd child I fork off the process and detach it from the calling process. This works fine most of the time. However in the unusual situation where apache needs to be restarted while the long running process is still running I can not restart apache. It complains that: 'Address already in use: make_sock: could not bind to address', which as far as I can make out is because the long running process has inherited the open sockets from the apache child. Has anyone got an idea how to get around this? Can I get to the inherited socket connection and close it when I have detached from the calling process? === To: Kees Vonk 7249 24549 <KEES.VONK@uktransco.com> From: Stas Bekman <stas@stason.org> Subject: Re: fork inherits socket connection Date: Thu, 14 Dec 2000 18:10:26 +0100 (CET) On Thu, 14 Dec 2000, Kees Vonk 7249 24549 wrote: > On our intranet server I have a page that allows the user to > start a long running process. In order not to hang a httpd > child I fork off the process and detach it from the calling > process. This works fine most of the time. > > However in the unusual situation where apache needs to be > restarted while the long running process is still running I > can not restart apache. It complains that: 'Address already > in use: make_sock: could not bind to address', which as far > as I can make out is because the long running process has > inherited the open sockets from the apache child. > > Has anyone got an idea how to get around this? Can I get to > the inherited socket connection and close it when I have > detached from the calling process? How about close STDOUT; close STDIN; close STDERR; in your child code? check this out: http://perl.apache.org/guide/performance.html#Forking_and_Executing_Subprocess it's explained there. === To: Kees Vonk 7249 24549 <KEES.VONK@uktransco.com> From: "G.W. Haywood" <ged@www.jubileegroup.co.uk> Subject: Re: fork inherits socket connection Date: Thu, 14 Dec 2000 17:45:44 +0000 (GMT) Hi there, On Thu, 14 Dec 2000, Kees Vonk 7249 24549 wrote: > However in the unusual situation where apache needs to be > restarted while the long running process is still running I > can not restart apache. It complains that: 'Address already > in use: make_sock: could not bind to address' We sometimes used to see this problem if a database server on the same machine had swallowed up a load of sockets in the 1025+ area and we were using high ports in the same area for developers to run private copies of Apache. You might want to try to make sure you're using known port numbers (er - as opposed to well-known port numbers :). === To: modperl <modperl@apache.org> From: Vivek Khera <khera@kciLink.com> Subject: Re: fork inherits socket connection Date: Thu, 14 Dec 2000 12:59:37 -0500 >>>>> "KV72" == Kees Vonk 7249 24549 <KEES.VONK@uktransco.com> writes: KV72> Has anyone got an idea how to get around this? Can I get to KV72> the inherited socket connection and close it when I have KV72> detached from the calling process? After you fork, why not close all open file descriptors you are not using? === To: Stas Bekman <stas@stason.org> From: Kees Vonk 7249 24549 <KEES.VONK@uktransco.com> Subject: Re: fork inherits socket connection Date: Tue, 19 Dec 2000 10:56:53 +0000 (GMT) > Kees, if you are doing system() call just put setsid back, > and add this: > > tie *OUT, 'Apache'; > close OUT; > > Apache keeps the socket tied. Tell me whether this works > for you. > > I'll document these things shortly and post for your > review. Adding (between fork and setsid): tie *OUT, 'Apache'; close OUT; causes the following error: Can't locate object method "TIEHANDLE" via package "Apache" at /app/env_control/bin/depldctl line 142. (where depldctl is my long running process). When I add 'use Apache;' I get the following error: Can't locate object method "request" via package "Apache" at /opt/perl5/lib/site_perl/PA-RISC2.0/Apache.pm line 191. any ideas? === To: Kees Vonk 7249 24549 <KEES.VONK@uktransco.com> From: Stas Bekman <stas@stason.org> Subject: Re: fork inherits socket connection Date: Tue, 19 Dec 2000 13:47:47 +0100 (CET) On Tue, 19 Dec 2000, Kees Vonk 7249 24549 wrote: > > Kees, if you are doing system() call just put setsid back, > > and add this: > > > > tie *OUT, 'Apache'; > > close OUT; > > > > Apache keeps the socket tied. Tell me whether this works > > for you. > > > > I'll document these things shortly and post for your > > review. > > Adding (between fork and setsid): > > tie *OUT, 'Apache'; > close OUT; > > causes the following error: > > Can't locate object method "TIEHANDLE" via package "Apache" > at /app/env_control/bin/depldctl line 142. > > (where depldctl is my long running process). > When I add 'use Apache;' I get the following error: > > Can't locate object method "request" via package "Apache" > at /opt/perl5/lib/site_perl/PA-RISC2.0/Apache.pm line 191. Yes, yes, yes it was a bad suggestion. Sorry about that. I still didn't complete this section, looking for a clean solution to find a way to close only the fd that keeps the socket busy. So far you can use the closing fds in loop -- at least it works. === To: Stas Bekman <stas@stason.org> From: Tom Brown <tbrown@baremetal.com> Subject: Re: fork inherits socket connection Date: Tue, 19 Dec 2000 10:06:56 -0800 (PST) > > Yes, yes, yes it was a bad suggestion. Sorry about that. > I still didn't complete this section, looking for a clean solution to find > a way to close only the fd that keeps the socket busy. > So far you can use the closing fds in loop -- at least it works. yuck... you'd either have to find some way to extract that information directly from apache, or loop through all the file descriptors calling getsockname() and then close any descriptor connected to port 80/443/? (depends how your daemon is setup, if you've got multiple Listen statements you will have to close multiple sockets ... but normally it would just be one or two (port 0.0.0.0:80 and/or 0.0.0.0:443) === To: Tom Brown <tbrown@baremetal.com> From: Stas Bekman <stas@stason.org> Subject: Re: fork inherits socket connection Date: Tue, 19 Dec 2000 19:13:30 +0100 (CET) On Tue, 19 Dec 2000, Tom Brown wrote: > > > > Yes, yes, yes it was a bad suggestion. Sorry about that. > > I still didn't complete this section, looking for a clean solution to find > > a way to close only the fd that keeps the socket busy. > > So far you can use the closing fds in loop -- at least it works. > > yuck... you'd either have to find some way to extract that information > directly from apache, or loop through all the file descriptors calling > getsockname() and then close any descriptor connected to port 80/443/? > (depends how your daemon is setup, if you've got multiple Listen > statements you will have to close multiple sockets ... but normally it > would just be one or two (port 0.0.0.0:80 and/or 0.0.0.0:443) The Apache API ap_note_cleanups_for_socket(p, s); does that, I'm trying to work this out with Apache::SubProcess. It works if you call system/exec, but I'm still looking to make it working with code running within fork without calling any variant of execve. I'll keep your posted, so far you have at least one working solution, even not the nicest one. === To: modperl <modperl@apache.org> From: Stas Bekman <stas@stason.org> Subject: Re: fork inherits socket connection Date: Tue, 19 Dec 2000 22:47:10 +0100 (CET) Below is a solution to this problem: * fork the long running process from mod_perl * and be able to restart the server o without killing this process o without this process keeping the socket busy and thus preventing the server restart Thanks to Doug for the hint. You need to patch Apache::SubProcess (CPAN): --- SubProcess.xs.orig Sat Sep 25 19:17:12 1999 +++ SubProcess.xs Tue Dec 19 21:03:22 2000 @@ -103,6 +103,14 @@ XPUSHs(io_hook(ioep, io_hook_read)); } + +void +ap_cleanup_after_fork(r) + Apache r + + CODE: + ap_cleanup_for_exec(); + int ap_call_exec(r, pgm=r->filename) Apache r which makes the new method available: cleanup_after_fork() This is the clean test case that shows that the conditions are fulfilled properly: use strict; use POSIX 'setsid'; use Apache::SubProcess; my $r = shift; $r->send_http_header("text/plain"); $SIG{CHLD} = 'IGNORE'; defined (my $kid = fork) or die "Cannot fork: $!\n"; if ($kid) { print "Parent $$ has finished, kid's PID: $kid\n"; } else { $r->cleanup_after_fork(); chdir '/' or die "Can't chdir to /: $!"; open STDIN, '/dev/null' or die "Can't read /dev/null: $!"; open STDOUT, '>/dev/null' or die "Can't write to /dev/null: $!"; open STDERR, '>/tmp/log' or die "Can't write to /tmp/log: $!"; setsid or die "Can't start a new session: $!"; local $|=1; warn "started\n"; # do something time-consuming sleep 1, warn "$_\n" for 1..20; warn "completed\n"; # we want the process to be terminated, Apache::exit() won't # terminate the process CORE::exit(0); } both processes are completely idependent now. Watch the /tmp/log as the forked process works, while you can restart the server. When I'll complete the rewrite of this section I'll post it all, with the solutions for exec/system as well (using Apache::SubProcess of course). And just a note, you always need setsid, so the server won't kill the spawned process when the server restarts. More cases/explanations to come soonish. Thanks to those who have raised this problem. === To: Stas Bekman <stas@stason.org> From: Kees Vonk 7249 24549 <KEES.VONK@uktransco.com> Subject: Re: fork inherits socket connection Date: Thu, 21 Dec 2000 10:45:19 +0000 (GMT) > Below is a solution to this problem: > > * fork the long running process from mod_perl > * and be able to restart the server > o without killing this process > o without this process keeping the socket busy > and thus preventing the server restart > > Thanks to Doug for the hint. You need to patch Apache::SubProcess > (CPAN): > > --- SubProcess.xs.orig Sat Sep 25 19:17:12 1999 > +++ SubProcess.xs Tue Dec 19 21:03:22 2000 > @@ -103,6 +103,14 @@ > XPUSHs(io_hook(ioep, io_hook_read)); > } > > + > +void > +ap_cleanup_after_fork(r) > + Apache r > + > + CODE: > + ap_cleanup_for_exec(); > + > int > ap_call_exec(r, pgm=r->filename) > Apache r > > > which makes the new method available: cleanup_after_fork() > > This is the clean test case that shows that the conditions are > fulfilled properly: > > use strict; > use POSIX 'setsid'; > use Apache::SubProcess; > > my $r = shift; > $r->send_http_header("text/plain"); > > $SIG{CHLD} = 'IGNORE'; > defined (my $kid = fork) or die "Cannot fork: $!\n"; > if ($kid) { > print "Parent $$ has finished, kid's PID: $kid\n"; > } else { > $r->cleanup_after_fork(); > chdir '/' or die "Can't chdir to /: $!"; > open STDIN, '/dev/null' or die "Can't read /dev/null: $!"; > open STDOUT, '>/dev/null' > or die "Can't write to /dev/null: $!"; > open STDERR, '>/tmp/log' or die "Can't write to /tmp/log: $!"; > setsid or die "Can't start a new session: $!"; > > local $|=1; > warn "started\n"; > # do something time-consuming > sleep 1, warn "$_\n" for 1..20; > warn "completed\n"; > # we want the process to be terminated, Apache::exit() won't > # terminate the process > CORE::exit(0); > } > > both processes are completely idependent now. Watch the /tmp/log as > the forked process works, while you can restart the server. Thank you very much, that works great and it looks much neater than what I had before. BTW. what is the function of the chdir '/', is that needed or can I leave that out? === To: Kees Vonk 7249 24549 <KEES.VONK@uktransco.com> From: Stas Bekman <stas@stason.org> Subject: Re: fork inherits socket connection Date: Thu, 21 Dec 2000 13:33:46 +0100 (CET) On Thu, 21 Dec 2000, Kees Vonk 7249 24549 wrote: > > Below is a solution to this problem: > > > > * fork the long running process from mod_perl > > * and be able to restart the server > > o without killing this process > > o without this process keeping the socket busy > > and thus preventing the server restart > > [snip] > > defined (my $kid = fork) or die "Cannot fork: $!\n"; > > if ($kid) { > > print "Parent $$ has finished, kid's PID: $kid\n"; > > } else { > > $r->cleanup_after_fork(); > > chdir '/' or die "Can't chdir to /: $!"; [snip] > Thank you very much, that works great and it looks much neater than what > I had before. thanks goes to doug for cleanup_after_fork :) BTW, in the official release it'll be called cleanup_for_exec(), so you better use this one from the beginning. > BTW. what is the function of the chdir '/', is that needed or can I > leave that out? it's useful in case you decide to umount the partition later, see perlipc manpage. You can leave it out of course. === To: Stas Bekman <stas@stason.org> From: Kees Vonk 7249 24549 <KEES.VONK@uktransco.com> Subject: Re: fork inherits socket connection Date: Thu, 21 Dec 2000 12:50:41 +0000 (GMT) > BTW, in the official release it'll be called > cleanup_for_exec(), so you better use this one from the > beginning. Does that mean I don't have to patch SubProcess.xs? Is cleanup_for_exec available by default? === To: Kees Vonk 7249 24549 <KEES.VONK@uktransco.com> From: Stas Bekman <stas@stason.org> Subject: Re: fork inherits socket connection Date: Thu, 21 Dec 2000 14:25:58 +0100 (CET) On Thu, 21 Dec 2000, Kees Vonk 7249 24549 wrote: > > BTW, in the official release it'll be called > > cleanup_for_exec(), so you better use this one from the > > beginning. > > Does that mean I don't have to patch SubProcess.xs? Is > cleanup_for_exec available by default? You'll have it in the next version of Apache::SubProcess. I suggested to adjust my patch to use cleanup_for_exec, so when you upgrade to the new Apache::SubProcess things won't go broken. === To: Kees Vonk 7249 24549 <KEES.VONK@uktransco.com> From: Stas Bekman <stas@stason.org> Subject: Re: fork inherits socket connection Date: Fri, 15 Dec 2000 13:07:46 +0100 (CET) On Fri, 15 Dec 2000, Kees Vonk 7249 24549 wrote: > Stas writes: > > How about > > > > close STDOUT; > > close STDIN; > > close STDERR; > > > > in your child code? > > > > check this out: > > > > http://perl.apache.org/guide/performance.html#Forking_and_Executing_Subprocess > > > > it's explained there. > > > I have tried closing STDOUT, STDIN and STDERR, but that > doesn't make any difference. > > What I do at the moment is: > > 1. Start the long running process (runs indefinitly for the > purpose of this test), which closes STDOUT, STDIN and > STDERR and then calls setsid(). Why do you call setsid()? Are you spawning a process with shell or fork? * If you spawn the process with fork remove setsid() and it'll work. * If you spawn the process with ``/system it works with what you've described. I've tested both on my machine. > I think the following might be the solution, we have done > that in a (not internet related) C program here to solve > almost the same problem. > > > Vivek writes: > > > KV72> Has anyone got an idea how to get around this? Can I get to > > KV72> the inherited socket connection and close it when I have > > KV72> detached from the calling process? > > > > After you fork, why not close all open file descriptors you are not > > using? What Vivek meant I suppose is the same: STDOUT and STDIN. > I have had a look throught the camel book. How do I close a > file descriptor (or find out if it is open), the perl close > function only accepts file handles. % perldoc -q descriptor Found in /usr/lib/perl5/5.6.0/pod/perlfaq5.pod How do I close a file descriptor by number? This should rarely be necessary, as the Perl close() function is to be used for things that Perl opened itself, even if it was a dup of a numeric descriptor, as with MHCONTEXT above. But if you really have to, you may be able to do this: require 'sys/syscall.ph'; $rc = syscall(&SYS_close, $fd + 0); # must force numeric die "can't sysclose $fd: $!" unless $rc == -1; Or just use the fdopen(3S) feature of open(): { local *F; open F, "<&=$fd" or die "Cannot reopen fd=$fd: $!"; close F; } === To: Stas Bekman <stas@stason.org> From: Kees Vonk 7249 24549 <KEES.VONK@uktransco.com> Subject: Re: fork inherits socket connection Date: Fri, 15 Dec 2000 12:36:52 +0000 (GMT) Stas, I had the following in my code: my($nOrgPID) = fork; exit if $nOrgPID; die "Could not fork: $!" unless defined $nOrgPID; close STDIN; close STDOUT; close STDERR; setsid() or die "Could not start new session: $!"; but that didn't work, however when I changed it to this: my($nOrgPID) = fork; exit if $nOrgPID; die "Could not fork: $!" unless defined $nOrgPID; require 'sys/syscall.ph'; for (my $i=0; $i<=255; $i++) { syscall(&SYS_close, $i + 0); # must force numeric } setsid() or die "Could not start new session: $!"; the socket got released and I could restart the server. I know it is a little crud, but it seems to work. === To: Kees Vonk 7249 24549 <KEES.VONK@uktransco.com> From: Stas Bekman <stas@stason.org> Subject: Re: fork inherits socket connection Date: Fri, 15 Dec 2000 13:46:28 +0100 (CET) On Fri, 15 Dec 2000, Kees Vonk 7249 24549 wrote: > Stas, > > I had the following in my code: > > my($nOrgPID) = fork; > exit if $nOrgPID; > die "Could not fork: $!" unless defined $nOrgPID; > > close STDIN; > close STDOUT; > close STDERR; > setsid() or die "Could not start new session: $!"; > > > but that didn't work, however when I changed it to this: > > my($nOrgPID) = fork; > exit if $nOrgPID; > die "Could not fork: $!" unless defined $nOrgPID; > > require 'sys/syscall.ph'; > for (my $i=0; $i<=255; $i++) { > syscall(&SYS_close, $i + 0); # must force numeric > } > > setsid() or die "Could not start new session: $!"; > > > the socket got released and I could restart the server. I > know it is a little crud, but it seems to work. But you don't need to call setsid() when you fork. Why looking for complicated workaround when you can do it properly without any workaround. Have you ever seen an example of fork that uses setsid? === To: "Stas Bekman" <stas@stason.org>, From: "Jeremy Howard" <jh_lists@fastmail.fm> Subject: Re: fork inherits socket connection Date: Sat, 16 Dec 2000 00:13:41 +1100 Stas Bekman wrote: > But you don't need to call setsid() when you fork. Why looking for > complicated workaround when you can do it properly without any workaround. > Have you ever seen an example of fork that uses setsid? > But your Guide says: ---- A much better approach would be to spawn a sub-process, hand it the information it needs to do the task, and have it detach (close STDIN, STDOUT and STDERR + execute setsid()). ---- === To: Jeremy Howard <jh_lists@fastmail.fm> From: Stas Bekman <stas@stason.org> Subject: Re: fork inherits socket connection Date: Fri, 15 Dec 2000 14:21:27 +0100 (CET) On Sat, 16 Dec 2000, Jeremy Howard wrote: > Stas Bekman wrote: > > But you don't need to call setsid() when you fork. Why looking for > > complicated workaround when you can do it properly without any workaround. > > Have you ever seen an example of fork that uses setsid? > > > But your Guide says: > ---- > A much better approach would be to spawn a sub-process, hand it the > information it needs to do the task, and have it detach (close STDIN, STDOUT > and STDERR + execute setsid()). > ---- True, it's a mish-mash of two techniques. I'm working at this very moment to make things clear. My follow-up was based on the fact that I told Kees in the original reply that setsid shoudn't be used with fork. Will be fixed in the next release, sorry about that. === To: Jeremy Howard <jh_lists@fastmail.fm> From: Stas Bekman <stas@stason.org> Subject: Re: fork inherits socket connection Date: Fri, 15 Dec 2000 14:27:08 +0100 (CET) On Fri, 15 Dec 2000, Stas Bekman wrote: > On Sat, 16 Dec 2000, Jeremy Howard wrote: > > > Stas Bekman wrote: > > > But you don't need to call setsid() when you fork. Why looking for > > > complicated workaround when you can do it properly without any workaround. > > > Have you ever seen an example of fork that uses setsid? > > > > > But your Guide says: > > ---- > > A much better approach would be to spawn a sub-process, hand it the > > information it needs to do the task, and have it detach (close STDIN, STDOUT > > and STDERR + execute setsid()). > > ---- In fact this is correct. You've taken this snippet out of the context. It was in the section talking about spawning a process without fork. So it's absolutely correct. === To: modperl <modperl@apache.org> From: "Richard L. Goerwitz" <richard@catlin.cis.brown.edu> Subject: Re: fork inherits socket connection Date: Fri, 15 Dec 2000 08:30:58 -0500 Stas Bekman wrote: > > 1. Start the long running process (runs indefinitly for the > > purpose of this test), which closes STDOUT, STDIN and > > STDERR and then calls setsid(). > > Why do you call setsid()? He's probably thinking of traditional the traditional way in which you background a daemon by forking, setsid'ing, then forking again to prevent the process from ever reacquiring a controlling terminal (your point, that this isn't needed here, is well taken). === To: Stas Bekman <stas@stason.org> From: Kees Vonk 7249 24549 <KEES.VONK@uktransco.com> Subject: Re: fork inherits socket connection Date: Fri, 15 Dec 2000 13:15:29 +0000 (GMT) > But you don't need to call setsid() when you fork. Why > looking for complicated workaround when you can do it > properly without any workaround. Have you ever seen an > example of fork that uses setsid? Ok, here is my confusion: I call the the long running process from the modperl script with a system() call that was why I was using the setsid() (in the longrunning process). I have now changed the code my long running process to: my($nOrgPID) = fork; exit if $nOrgPID; die "Could not fork: $!" unless defined $nOrgPID; close STDIN; close STDOUT; close STDERR; and that does not work, I have also tried putting it in the modperl script instead but that doesn't work either. What am I doing wrong and why would the setsid() be a showstopper, especially as it is called after the close statements (it doesn't reopen the filehandles does it). I could understand that it would possibly be unnecessary, but how could it stop this code from working? Another (more detailed) run through. 1. modperl script starts long running process (lrp) with a system() call. 2. lrp runs the code above (fork + close (tried this with and without setsid)). 3. stop apache 4. start apache - fails (port in use) 5. netstat -na reveals port in LISTEN state. 6. kill lrp 7. netstat -na reveals port no longer in use. 8. start apache - now starts fine I think I am doing something wrong somewhere, but I am not sure where. Is it right that I have to do the system call and the fork? === To: Stas Bekman <stas@stason.org> From: Rafael Caceres <rcaceres@aasa.com.pe> Subject: Re: fork inherits socket connection Date: Fri, 15 Dec 2000 08:44:05 -0500 At 01:46 PM 12/15/00 +0100, you wrote: >On Fri, 15 Dec 2000, Kees Vonk 7249 24549 wrote: > > > Stas, > > > > I had the following in my code: > > > > my($nOrgPID) = fork; > > exit if $nOrgPID; > > die "Could not fork: $!" unless defined $nOrgPID; > > > > close STDIN; > > close STDOUT; > > close STDERR; > > setsid() or die "Could not start new session: $!"; > > > > > > but that didn't work, however when I changed it to this: > > > > my($nOrgPID) = fork; > > exit if $nOrgPID; > > die "Could not fork: $!" unless defined $nOrgPID; > > > > require 'sys/syscall.ph'; > > for (my $i=0; $i<=255; $i++) { > > syscall(&SYS_close, $i + 0); # must force numeric > > } > > > > setsid() or die "Could not start new session: $!"; > > > > > > the socket got released and I could restart the server. I > > know it is a little crud, but it seems to work. > >But you don't need to call setsid() when you fork. Why looking for >complicated workaround when you can do it properly without any workaround. >Have you ever seen an example of fork that uses setsid? Yes, the following is taken straight out from the perlipc documentation: ----------------------------- Complete Dissociation of Child from Parent In some cases (starting server processes, for instance) you'll want to completely dissociate the child process from the parent. This is often called daemonization. A well behaved daemon will also chdir() to the root directory (so it doesn't prevent unmounting the filesystem containing the directory from which it was launched) and redirect its standard file descriptors from and to /dev/null (so that random output doesn't wind up on the user's terminal). use POSIX 'setsid'; sub daemonize { chdir '/' or die "Can't chdir to /: $!"; open STDIN, '/dev/null' or die "Can't read /dev/null: $!"; open STDOUT, '>/dev/null' or die "Can't write to /dev/null: $!"; defined(my $pid = fork) or die "Can't fork: $!"; exit if $pid; setsid or die "Can't start a new session: $!"; open STDERR, '>&STDOUT' or die "Can't dup stdout: $!"; } The fork() has to come before the setsid() to ensure that you aren't a process group leader (the setsid() will fail if you are). If your system doesn't have the setsid() function, open /dev/tty and use the TIOCNOTTY ioctl() on it instead. See tty(4) for details. === To: Kees Vonk 7249 24549 <KEES.VONK@uktransco.com> From: Stas Bekman <stas@stason.org> Subject: Re: fork inherits socket connection Date: Fri, 15 Dec 2000 15:58:00 +0100 (CET) On Fri, 15 Dec 2000, Kees Vonk 7249 24549 wrote: > > But you don't need to call setsid() when you fork. Why > > looking for complicated workaround when you can do it > > properly without any workaround. Have you ever seen an > > example of fork that uses setsid? > > Ok, > > here is my confusion: I call the the long running process > from the modperl script with a system() call that was why I > was using the setsid() (in the longrunning process). > > I have now changed the code my long running process to: > > my($nOrgPID) = fork; > exit if $nOrgPID; > die "Could not fork: $!" unless defined $nOrgPID; > > close STDIN; > close STDOUT; > close STDERR; > > > and that does not work, I have also tried putting it in the > modperl script instead but that doesn't work either. Kees, if you are doing system() call just put setsid back, and add this: tie *OUT, 'Apache'; close OUT; Apache keeps the socket tied. Tell me whether this works for you. I'll document these things shortly and post for your review. === To: Rafael Caceres <rcaceres@aasa.com.pe> From: Stas Bekman <stas@stason.org> Subject: Re: fork inherits socket connection Date: Fri, 15 Dec 2000 16:02:11 +0100 (CET) > >But you don't need to call setsid() when you fork. Why looking for > >complicated workaround when you can do it properly without any workaround. > >Have you ever seen an example of fork that uses setsid? > > Yes, the following is taken straight out from the perlipc documentation: > ----------------------------- > Complete Dissociation of Child from Parent > > In some cases (starting server processes, for instance) you'll want to > completely dissociate the child process from the > parent. This is often called daemonization. A well behaved daemon will also > chdir() to the root directory (so it > doesn't prevent unmounting the filesystem containing the directory from > which it was launched) and redirect its standard > file descriptors from and to /dev/null (so that random output doesn't wind > up on the user's terminal). > > use POSIX 'setsid'; > > sub daemonize { > chdir '/' or die "Can't chdir to /: $!"; > open STDIN, '/dev/null' or die "Can't read /dev/null: $!"; > open STDOUT, '>/dev/null' > or die "Can't write to /dev/null: $!"; > defined(my $pid = fork) or die "Can't fork: $!"; > exit if $pid; > setsid or die "Can't start a new session: $!"; > open STDERR, '>&STDOUT' or die "Can't dup stdout: $!"; > } > > The fork() has to come before the setsid() to ensure that you aren't a > process group leader (the setsid() will fail if you are). If your system > doesn't have the setsid() function, open /dev/tty and use the TIOCNOTTY > ioctl() on it instead. See tty(4) for details. > ----------------- > > Am I missing something? You don't miss anything, the above code is an example of daemonization. You don't really need to call setsid() for a *forked* process that was started to execute something and quit. It's different if you call system() to spawn the process. But since it's a child of the parent httpd it's not a leader anyway so you don't need the extra fork I suppose. Am I correct? In fact it's good that you've posted this doc snippet, I'll use it as it's more complete and cleaner. Thanks. === To: modperl@apache.org From: Bill Moseley <moseley@hank.org> Subject: Re: fork inherits socket connection Date: Fri, 15 Dec 2000 07:24:27 -0800 At 04:02 PM 12/15/00 +0100, Stas Bekman wrote: >> Am I missing something? > >You don't miss anything, the above code is an example of daemonization. >You don't really need to call setsid() for a *forked* process that was >started to execute something and quit. > >It's different if you call system() to spawn the process. But since it's a >child of the parent httpd it's not a leader anyway so you don't need the >extra fork I suppose. Am I correct? > >In fact it's good that you've posted this doc snippet, I'll use it as it's >more complete and cleaner. Thanks. Thank goodness! I like this thread -- It's been hard keeping up with all the posts just to see if PHP or Java is better than mod_perl ;) Stas, will you please post your additions/notification about this when you are done? I do hope you go into a bit of detail on this, as I've posted questions about setsid a number of times and locations and I'm still unclear about when or when not to use it, why to use it, and how that might relate to mod_perl and why it makes a difference between system() vs. fork. I've just blindly followed perlipc's recommendations. BTW -- this isn't related to the infrequently reported problem of an Apache child that won't die even with kill -9, is it? === To: modperl <modperl@apache.org> From: Vivek Khera <khera@kciLink.com> Subject: Re: fork inherits socket connection Date: Fri, 15 Dec 2000 10:50:33 -0500 >>>>> "KV72" == Kees Vonk 7249 24549 <KEES.VONK@uktransco.com> writes: KV72> require 'sys/syscall.ph'; KV72> for (my $i=0; $i<=255; $i++) { KV72> syscall(&SYS_close, $i + 0); # must force numeric KV72> } KV72> the socket got released and I could restart the server. I KV72> know it is a little crud, but it seems to work. No, it is not crud. If you want your forked process to act like a daemon, you must make sure to perform the necessary actions. That includes closing all open file descriptors you are not using. === To: modperl <modperl@apache.org> From: Vivek Khera <khera@kciLink.com> Subject: Re: fork inherits socket connection Date: Fri, 15 Dec 2000 10:56:35 -0500 >>>>> "SB" == Stas Bekman <stas@stason.org> writes: SB> In fact this is correct. You've taken this snippet out of the context. It SB> was in the section talking about spawning a process without fork. So it's SB> absolutely correct. How exactly does one spawn a process without fork() in unix? (It is a rhetorical question, in case you didn't figure that out.) === To: Vivek Khera <khera@kciLink.com> From: Stas Bekman <stas@stason.org> Subject: Re: fork inherits socket connection Date: Fri, 15 Dec 2000 17:07:57 +0100 (CET) On Fri, 15 Dec 2000, Vivek Khera wrote: > >>>>> "SB" == Stas Bekman <stas@stason.org> writes: > > SB> In fact this is correct. You've taken this snippet out of the context. It > SB> was in the section talking about spawning a process without fork. So it's > SB> absolutely correct. > > How exactly does one spawn a process without fork() in unix? > > (It is a rhetorical question, in case you didn't figure that out.) Hold on folks, gimme a little time and I'll come up with a clear explanation of all the mess that I admittedly created. I'll post the fresh corrected docs and then you will tell me if some things are still vague... Ok? Thanks for your patience. === To: modperl@apache.org From: Bill Moseley <moseley@hank.org> Subject: Re: fork inherits socket connection Date: Fri, 15 Dec 2000 15:32:50 -0800 At 04:02 PM 12/15/00 +0100, Stas Bekman wrote: >> open STDIN, '/dev/null' or die "Can't read /dev/null: $!"; >> open STDOUT, '>/dev/null' >> or die "Can't write to /dev/null: $!"; >> defined(my $pid = fork) or die "Can't fork: $!"; >> exit if $pid; >> setsid or die "Can't start a new session: $!"; >> open STDERR, '>&STDOUT' or die "Can't dup stdout: $!"; >You don't miss anything, the above code is an example of daemonization. >You don't really need to call setsid() for a *forked* process that was >started to execute something and quit. Oh, so that's the difference between system and fork/exec! That's what I get for following perlipc instead of the Guide. I've always done it the Hard Way (tm) before. That is, in my mod_perl handler I would fork, then waitpid, call setsid, fork again freeing Apache to continue (and double fork to avoid zombies), and then finally exec my long running program. With this method I had to call setsid or else killing the Apache parent would kill the long running process. Calling system() in the handler and then doing a simple fork in the long running program is much cleaner (but you all knew that already). I just didn't realize that it freed me from calling setsid. I just have to remember not to system() something that doesn't fork or return right away. But, I'm really posting about the original problem of the socket bound the by the forked program. I tried looking through mod_cgi to see why mod_cgi can fork off a long running process that won't hold the socket open but I my poor reading of it didn't turn anything up. Anyone familiar enough with Apache (and/or mod_cgi) to explain the difference? Does mod_cgi explicitly close the socket file descriptor(s) before forking? ===