You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Kees Vonk 7249 24549 <KE...@uktransco.com> on 2000/12/14 16:36:26 UTC

fork inherits socket connection

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?


Kees Vonk

Re: fork inherits socket connection

Posted by Vivek Khera <kh...@kciLink.com>.
>>>>> "KV72" == Kees Vonk 7249 24549 <KE...@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?

-- 
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Vivek Khera, Ph.D.                Khera Communications, Inc.
Internet: khera@kciLink.com       Rockville, MD       +1-240-453-8497
AIM: vivekkhera Y!: vivek_khera   http://www.khera.org/~vivek/

Re: fork inherits socket connection

Posted by "G.W. Haywood" <ge...@www.jubileegroup.co.uk>.
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 :).

73,
Ged.



Re: fork inherits socket connection

Posted by "Richard L. Goerwitz" <ri...@catlin.cis.brown.edu>.
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).

-- 
Richard Goerwitz				Richard_Goerwitz@Brown.EDU

Re: fork inherits socket connection

Posted by Vivek Khera <kh...@kciLink.com>.
>>>>> "KV72" == Kees Vonk 7249 24549 <KE...@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.

-- 
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Vivek Khera, Ph.D.                Khera Communications, Inc.
Internet: khera@kciLink.com       Rockville, MD       +1-240-453-8497
AIM: vivekkhera Y!: vivek_khera   http://www.khera.org/~vivek/

Re: fork inherits socket connection

Posted by Bill Moseley <mo...@hank.org>.
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?

Thanks,


Bill Moseley
mailto:moseley@hank.org

Re: fork inherits socket connection

Posted by Bill Moseley <mo...@hank.org>.
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?

Eagerly awaiting,



Bill Moseley
mailto:moseley@hank.org

Re: fork inherits socket connection

Posted by Stas Bekman <st...@stason.org>.
> >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.


_____________________________________________________________________
Stas Bekman              JAm_pH     --   Just Another mod_perl Hacker
http://stason.org/       mod_perl Guide  http://perl.apache.org/guide 
mailto:stas@stason.org   http://apachetoday.com http://logilune.com/
http://singlesheaven.com http://perl.apache.org http://perlmonth.com/  



Re: fork inherits socket connection

Posted by Rafael Caceres <rc...@aasa.com.pe>.
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.
-----------------

Am I missing something?

Regards,
Rafael Caceres




Re: fork inherits socket connection

Posted by Stas Bekman <st...@stason.org>.
On Fri, 15 Dec 2000, Vivek Khera wrote:

> >>>>> "SB" == Stas Bekman <st...@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.

_____________________________________________________________________
Stas Bekman              JAm_pH     --   Just Another mod_perl Hacker
http://stason.org/       mod_perl Guide  http://perl.apache.org/guide 
mailto:stas@stason.org   http://apachetoday.com http://logilune.com/
http://singlesheaven.com http://perl.apache.org http://perlmonth.com/  



Re: fork inherits socket connection

Posted by Vivek Khera <kh...@kciLink.com>.
>>>>> "SB" == Stas Bekman <st...@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.)

-- 
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Vivek Khera, Ph.D.                Khera Communications, Inc.
Internet: khera@kciLink.com       Rockville, MD       +1-240-453-8497
AIM: vivekkhera Y!: vivek_khera   http://www.khera.org/~vivek/

Re: fork inherits socket connection

Posted by Stas Bekman <st...@stason.org>.
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.


_____________________________________________________________________
Stas Bekman              JAm_pH     --   Just Another mod_perl Hacker
http://stason.org/       mod_perl Guide  http://perl.apache.org/guide 
mailto:stas@stason.org   http://apachetoday.com http://logilune.com/
http://singlesheaven.com http://perl.apache.org http://perlmonth.com/  



Re: fork inherits socket connection

Posted by Stas Bekman <st...@stason.org>.
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.

_____________________________________________________________________
Stas Bekman              JAm_pH     --   Just Another mod_perl Hacker
http://stason.org/       mod_perl Guide  http://perl.apache.org/guide 
mailto:stas@stason.org   http://apachetoday.com http://logilune.com/
http://singlesheaven.com http://perl.apache.org http://perlmonth.com/  



Re: fork inherits socket connection

Posted by Jeremy Howard <jh...@fastmail.fm>.
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()).
----



Re: fork inherits socket connection

Posted by Stas Bekman <st...@stason.org>.
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.

_____________________________________________________________________
Stas Bekman              JAm_pH     --   Just Another mod_perl Hacker
http://stason.org/       mod_perl Guide  http://perl.apache.org/guide 
mailto:stas@stason.org   http://apachetoday.com http://logilune.com/
http://singlesheaven.com http://perl.apache.org http://perlmonth.com/  



Re: fork inherits socket connection

Posted by Kees Vonk 7249 24549 <KE...@uktransco.com>.
> 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?


Kees


Re: fork inherits socket connection

Posted by Stas Bekman <st...@stason.org>.
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.

_____________________________________________________________________
Stas Bekman              JAm_pH     --   Just Another mod_perl Hacker
http://stason.org/       mod_perl Guide  http://perl.apache.org/guide 
mailto:stas@stason.org   http://apachetoday.com http://logilune.com/
http://singlesheaven.com http://perl.apache.org http://perlmonth.com/  



Re: fork inherits socket connection

Posted by Kees Vonk 7249 24549 <KE...@uktransco.com>.
> 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?


Kees


Re: fork inherits socket connection

Posted by Stas Bekman <st...@stason.org>.
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.

_____________________________________________________________________
Stas Bekman              JAm_pH     --   Just Another mod_perl Hacker
http://stason.org/       mod_perl Guide  http://perl.apache.org/guide 
mailto:stas@stason.org   http://apachetoday.com http://logilune.com/
http://singlesheaven.com http://perl.apache.org http://perlmonth.com/  



Re: fork inherits socket connection

Posted by Stas Bekman <st...@stason.org>.
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.


_____________________________________________________________________
Stas Bekman              JAm_pH     --   Just Another mod_perl Hacker
http://stason.org/       mod_perl Guide  http://perl.apache.org/guide 
mailto:stas@stason.org   http://apachetoday.com http://logilune.com/
http://singlesheaven.com http://perl.apache.org http://perlmonth.com/  



Re: fork inherits socket connection

Posted by Tom Brown <tb...@baremetal.com>.
> 
> 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)

----------------------------------------------------------------------
tbrown@BareMetal.com   | Don't go around saying the world owes you a living;
http://BareMetal.com/  | the world owes you nothing; it was here first.
web hosting since '95  | - Mark Twain


Re: fork inherits socket connection

Posted by Stas Bekman <st...@stason.org>.
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.


_____________________________________________________________________
Stas Bekman              JAm_pH     --   Just Another mod_perl Hacker
http://stason.org/       mod_perl Guide  http://perl.apache.org/guide 
mailto:stas@stason.org   http://apachetoday.com http://logilune.com/
http://singlesheaven.com http://perl.apache.org http://perlmonth.com/  



Re: fork inherits socket connection

Posted by Kees Vonk 7249 24549 <KE...@uktransco.com>.
> 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?

Kees


Re: fork inherits socket connection

Posted by Stas Bekman <st...@stason.org>.

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.


> 
> 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?
> 
> Kees
> 
> 
> 



_____________________________________________________________________
Stas Bekman              JAm_pH     --   Just Another mod_perl Hacker
http://stason.org/       mod_perl Guide  http://perl.apache.org/guide 
mailto:stas@stason.org   http://apachetoday.com http://logilune.com/
http://singlesheaven.com http://perl.apache.org http://perlmonth.com/  



Re: fork inherits socket connection

Posted by Kees Vonk 7249 24549 <KE...@uktransco.com>.
> 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?

Kees



Re: fork inherits socket connection

Posted by Stas Bekman <st...@stason.org>.
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?

_____________________________________________________________________
Stas Bekman              JAm_pH     --   Just Another mod_perl Hacker
http://stason.org/       mod_perl Guide  http://perl.apache.org/guide 
mailto:stas@stason.org   http://apachetoday.com http://logilune.com/
http://singlesheaven.com http://perl.apache.org http://perlmonth.com/  



Re: fork inherits socket connection

Posted by Kees Vonk 7249 24549 <KE...@uktransco.com>.
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.


Kees


Re: fork inherits socket connection

Posted by Stas Bekman <st...@stason.org>.
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;
           }



_____________________________________________________________________
Stas Bekman              JAm_pH     --   Just Another mod_perl Hacker
http://stason.org/       mod_perl Guide  http://perl.apache.org/guide 
mailto:stas@stason.org   http://apachetoday.com http://logilune.com/
http://singlesheaven.com http://perl.apache.org http://perlmonth.com/  



Re: fork inherits socket connection

Posted by Kees Vonk 7249 24549 <KE...@uktransco.com>.
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().

2. Stop the apache server.

3. Start the apache server (this fails).

4. netstat -na reveals that the port it tries to use is still 
   in LISTEN state.

5. Kill the long running process.

6. Start the apache server (this now works).


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? 
 

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.



Kees


Re: fork inherits socket connection

Posted by Stas Bekman <st...@stason.org>.
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.

_____________________________________________________________________
Stas Bekman              JAm_pH     --   Just Another mod_perl Hacker
http://stason.org/       mod_perl Guide  http://perl.apache.org/guide 
mailto:stas@stason.org   http://apachetoday.com http://logilune.com/
http://singlesheaven.com http://perl.apache.org http://perlmonth.com/