You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Victor Danilchenko <vi...@askonline.net> on 2009/08/25 14:11:40 UTC

Help -- how to fork an Apache process in mod_perl safely? Not Apache2:Subprocess...

	Hi all,

	I need to be able to fork an Apache process in daemon form, to do some 
housekeeping which might potentially take a few seconds. However, when I 
do that, I start getting SQL errors (of the "connection lost" type) in 
the browser. I do the fairly standard cleanup to daemonize the child 
process, but of course it needs to retain the SQL socket open. Here is 
my forking code:

sub modperl_kamikaze_fork () {
     # You will have to do CORE::exit(0) at the end of the execution.

     $SIG{CHLD} = 'IGNORE';
     get_m->flush_buffer;
     defined (my $kid = fork) or die "Cannot fork: $!\n";
     return $kid if $kid;

     my $r = get_r;
     close STDIN; open STDIN, '/dev/null'
	or die "Can't read /dev/null: $!";
     close STDOUT; open STDOUT, '>/dev/null'
	or die "Can't write to /dev/null: $!";
     close STDERR; open STDERR, '>>/tmp/form.log'
	or die "Cannot open /tmp/fork.log\n";
     setsid
	or die "Can't start a new session: $!";

     my $oldfh = select STDERR;
     local $| = 1;
     select $oldfh;
     warn "Child (PID $$) spawned.\n";

     $r->child_terminate;
}


	The Apache2:Subprocess doesn't help me, because I need not to spawn an 
external process, but to finish processing in mod_perl context -- just 
without bugging the user with it.

	Any ideas on how to either fork better, or how to solve this without 
forking (e.g. is there a way to 'append' a function call to the request 
after the rest of the request is completed)?

	Many thanks in advance.

-- 
	Victor Danilchenko
	Senior Software Engineer, AskOnline.net
	victor@askonline.net - 617-273-0119

Re: Help -- how to fork an Apache process in mod_perl safely? Not Apache2:Subprocess...

Posted by Igor Chudov <ic...@gmail.com>.
my solution is here:

sub fork_temporary_child {
  my $result = fork();
  unless( $result ) {
    # Do not use SQL in child
    dbh->{InactiveDestroy} = 1;
    disconnect_dbh;
  }
  return $result;
}



On Tue, Aug 25, 2009 at 7:11 AM, Victor Danilchenko <vi...@askonline.net>wrote:

>        Hi all,
>
>        I need to be able to fork an Apache process in daemon form, to do
> some housekeeping which might potentially take a few seconds. However, when
> I do that, I start getting SQL errors (of the "connection lost" type) in the
> browser. I do the fairly standard cleanup to daemonize the child process,
> but of course it needs to retain the SQL socket open. Here is my forking
> code:
>
> sub modperl_kamikaze_fork () {
>    # You will have to do CORE::exit(0) at the end of the execution.
>
>    $SIG{CHLD} = 'IGNORE';
>    get_m->flush_buffer;
>    defined (my $kid = fork) or die "Cannot fork: $!\n";
>    return $kid if $kid;
>
>    my $r = get_r;
>    close STDIN; open STDIN, '/dev/null'
>        or die "Can't read /dev/null: $!";
>    close STDOUT; open STDOUT, '>/dev/null'
>        or die "Can't write to /dev/null: $!";
>    close STDERR; open STDERR, '>>/tmp/form.log'
>        or die "Cannot open /tmp/fork.log\n";
>    setsid
>        or die "Can't start a new session: $!";
>
>    my $oldfh = select STDERR;
>    local $| = 1;
>    select $oldfh;
>    warn "Child (PID $$) spawned.\n";
>
>    $r->child_terminate;
> }
>
>
>        The Apache2:Subprocess doesn't help me, because I need not to spawn
> an external process, but to finish processing in mod_perl context -- just
> without bugging the user with it.
>
>        Any ideas on how to either fork better, or how to solve this without
> forking (e.g. is there a way to 'append' a function call to the request
> after the rest of the request is completed)?
>
>        Many thanks in advance.
>
> --
>        Victor Danilchenko
>        Senior Software Engineer, AskOnline.net
>        victor@askonline.net - 617-273-0119
>

Re: Help -- how to fork an Apache process in mod_perl safely? Not Apache2:Subprocess...

Posted by Victor Danilchenko <vi...@askonline.net>.
William T wrote:
> There are all kinds of problems that you'll encounter and have to solve 
> if you fork.  I found it's better to call at(1) to start another 
> seperate process immediatly.  If you need to pass data JSON worked 
> really well for me.

	Thanks, that's what I ended up doing. First I ended up having to move 
the processing into an external script call anyway, and then I tried 
Apache2::SubProcess, and it ended up working, but my script was randomly 
receiving TERM signals... it's handleable of course, but I decided to go 
with the 'at' technique, it's safer that way, I suppose.



>> On Aug 25, 2009 5:12 AM, "Victor Danilchenko" <victor@askonline.net 
>> <ma...@askonline.net>> wrote:
>>
>>        Hi all,
>>
>>        I need to be able to fork an Apache process in daemon form, to 
>> do some housekeeping which might potentially take a few seconds. 
>> However, when I do that, I start getting SQL errors (of the 
>> "connection lost" type) in the browser. I do the fairly standard 
>> cleanup to daemonize the child process, but of course it needs to 
>> retain the SQL socket open. Here is my forking code:
>>
>> sub modperl_kamikaze_fork () {
>>    # You will have to do CORE::exit(0) at the end of the execution.
>>
>>    $SIG{CHLD} = 'IGNORE';
>>    get_m->flush_buffer;
>>    defined (my $kid = fork) or die "Cannot fork: $!\n";
>>    return $kid if $kid;
>>
>>    my $r = get_r;
>>    close STDIN; open STDIN, '/dev/null'
>>        or die "Can't read /dev/null: $!";
>>    close STDOUT; open STDOUT, '>/dev/null'
>>        or die "Can't write to /dev/null: $!";
>>    close STDERR; open STDERR, '>>/tmp/form.log'
>>        or die "Cannot open /tmp/fork.log\n";
>>    setsid
>>        or die "Can't start a new session: $!";
>>
>>    my $oldfh = select STDERR;
>>    local $| = 1;
>>    select $oldfh;
>>    warn "Child (PID $$) spawned.\n";
>>
>>    $r->child_terminate;
>> }
>>
>>
>>        The Apache2:Subprocess doesn't help me, because I need not to 
>> spawn an external process, but to finish processing in mod_perl 
>> context -- just without bugging the user with it.
>>
>>        Any ideas on how to either fork better, or how to solve this 
>> without forking (e.g. is there a way to 'append' a function call to 
>> the request after the rest of the request is completed)?
>>
>>        Many thanks in advance.
>>
>> -- 
>>        Victor Danilchenko
>>        Senior Software Engineer, AskOnline.net
>>        victor@askonline.net <ma...@askonline.net> - 617-273-0119
> 


-- 
	Victor Danilchenko
	Senior Software Engineer, AskOnline.net
	victor@askonline.net - 617-273-0119

Re: Help -- how to fork an Apache process in mod_perl safely? Not Apache2:Subprocess...

Posted by William T <di...@gmail.com>.
There are all kinds of problems that you'll encounter and have to solve if
you fork.  I found it's better to call at(1) to start another seperate
process immediatly.  If you need to pass data JSON worked really well for
me.

-wjt

On Aug 25, 2009 5:12 AM, "Victor Danilchenko" <vi...@askonline.net> wrote:

       Hi all,

       I need to be able to fork an Apache process in daemon form, to do
some housekeeping which might potentially take a few seconds. However, when
I do that, I start getting SQL errors (of the "connection lost" type) in the
browser. I do the fairly standard cleanup to daemonize the child process,
but of course it needs to retain the SQL socket open. Here is my forking
code:

sub modperl_kamikaze_fork () {
   # You will have to do CORE::exit(0) at the end of the execution.

   $SIG{CHLD} = 'IGNORE';
   get_m->flush_buffer;
   defined (my $kid = fork) or die "Cannot fork: $!\n";
   return $kid if $kid;

   my $r = get_r;
   close STDIN; open STDIN, '/dev/null'
       or die "Can't read /dev/null: $!";
   close STDOUT; open STDOUT, '>/dev/null'
       or die "Can't write to /dev/null: $!";
   close STDERR; open STDERR, '>>/tmp/form.log'
       or die "Cannot open /tmp/fork.log\n";
   setsid
       or die "Can't start a new session: $!";

   my $oldfh = select STDERR;
   local $| = 1;
   select $oldfh;
   warn "Child (PID $$) spawned.\n";

   $r->child_terminate;
}


       The Apache2:Subprocess doesn't help me, because I need not to spawn
an external process, but to finish processing in mod_perl context -- just
without bugging the user with it.

       Any ideas on how to either fork better, or how to solve this without
forking (e.g. is there a way to 'append' a function call to the request
after the rest of the request is completed)?

       Many thanks in advance.

-- 
       Victor Danilchenko
       Senior Software Engineer, AskOnline.net
       victor@askonline.net - 617-273-0119

Re: Help -- how to fork an Apache process in mod_perl safely? Not Apache2:Subprocess...

Posted by Perrin Harkins <ph...@gmail.com>.
On Tue, Aug 25, 2009 at 8:11 AM, Victor Danilchenko<vi...@askonline.net> wrote:
>        I need to be able to fork an Apache process in daemon form, to do
> some housekeeping which might potentially take a few seconds. However, when
> I do that, I start getting SQL errors (of the "connection lost" type) in the
> browser. I do the fairly standard cleanup to daemonize the child process,
> but of course it needs to retain the SQL socket open.

You can't fork and keep using a database connection.  You have to open
a new connection in the forked process.

>        The Apache2:Subprocess doesn't help me, because I need not to spawn
> an external process, but to finish processing in mod_perl context -- just
> without bugging the user with it.

In that case, just use a cleanup handler instead.

- Perrin