
tosh at 1200group
Feb 20, 2010, 7:01 AM
Post #6 of 6
(760 views)
Permalink
|
|
Re: Apache2::SubProcess subprocess not subprocessing properly
[In reply to]
|
|
You aren't going to like this, and maybe what you're doing is for a really complex situation, but it really shouldn't be so complex to just spawn off a long running process that you don't care to ever hear back from, honestly. Tosh Torsten Förtsch wrote: > Tosh, > > On Tuesday 09 February 2010 14:21:57 Tosh Cooey wrote: >> Hi after much trial and all error I am seeing that the browser >> connection closing is also stopping my subprocess. >> > > I don't know what you are trying to achieve and I don't use > Apache2::Subprocess much. What I do to fork off processes instead is this: > > my $close_fd=sub { > use POSIX (); > my %save=(2=>1); # keep STDERR > undef @save{@_} if( @_ ); > opendir my $d, "/proc/self/fd" or do { > warn "Cannot open directory /proc/self/fd: $!\n"; > POSIX::_exit -1; # try this first to avoid buffer flushing > CORE::exit -1; > }; > > while (defined(my $fd=readdir $d)) { > next unless $fd=~/^\d+$/; > POSIX::close $fd unless exists $save{$fd}; > } > }; > > my $spawn=sub { > use POSIX (); > my ($daemon_should_survive_apache_restart, @args)=@_; > > local $SIG{CHLD}='IGNORE'; > my $pid; > # yes, even fork can fail > select undef, undef, undef, .1 while( !defined($pid=fork) ); > unless( $pid ) { # child > # 2nd fork to cut parent relationship with a mod_perl apache > select undef, undef, undef, .1 while( !defined($pid=fork) ); > if( $pid ) { > POSIX::_exit 0; > CORE::exit 0; > } else { > if( ref($daemon_should_survive_apache_restart) ) { > $close_fd->($daemon_should_survive_apache_restart->{fd}); > POSIX::setsid if( $daemon_should_survive_apache_restart->{survive} ); > } else { > $close_fd->(); > POSIX::setsid if( $daemon_should_survive_apache_restart ); > } > > if( 'CODE' eq ref $args[0] ) { > my $f=shift @args; > # TODO: restore %ENV and exit() behavior > eval {$f->(@args)}; > CORE::exit 0; > } else { > {exec @args;} # extra block to suppress a warning > POSIX::_exit -1; > CORE::exit -1; > } > } > } > waitpid $pid, 0; # avoid a zombie on some OS > }; > > And this is how to use it: > > $spawn->({survive=>1}, sub { > my ($n, $sleep)=@_; > for(1..$n) { > warn "sleeping $sleep\n"; > sleep $sleep; > } > warn "Done\n"; > }, 10, 2 ); > > or > > $spawn-> > (undef, # don't survive apache stop > qw/bash -c/,'for (( i=0; i<10; i++ )); do echo "opi" >&2; sleep 2; done') > > The first argument to $spawn is an options hash with 2 possible options: > > survive=>BOOLEAN # should the subprocess survive an apache stop or not > fd=>\@list_of_open_file_descriptors_to_preserve > > Normally the $spawn will close all files save for STDERR. With the fd option > one can preserve other files such as database connections or other. > > With the survive option true the child process will be the leader of a new > process group. > > NOTES: > > - The $close_fd function is Linux-specific. I couldn't think of a really > portable (at least across UNICES) way to get all open file descriptors of the > current process. > > - The waitpid at the end of $spawn is not necessary under Linux since > $SIG{CHLD}='IGNORE' already takes care of zombies. But other systems need it. > > - Keep in mind that %ENV and exit() work different under mod_perl. If you pass > a subroutine this behavior remains. > > Torsten > -- McIntosh Cooey - Twelve Hundred Group LLC - http://www.1200group.com/
|