Re: mod_perl v2 Forking

2003-09-16 Thread Stas Bekman
Cameron B. Prince wrote:

I have a report generator program written in Perl that I need to start from
a CGI. The program takes about 15 minutes to run, so I must fork or double
fork. I have two goals:
1) Have no zombies when the program completes
2) Fork in such a way that restarting Apache doesn't kill the forked
process.
I tried out the code here which is for mod_perl v1:

http://perl.apache.org/docs/1.0/guide/performance.html#Forking_and_Executing
_Subprocesses_from_mod_perl
There are two problems with the code listed in the example:

1) Apache::SubProcess doesn't seem to contain the same methods as the older
version.
most of them aren't needed (they don't exist in the Apache 2.0 API.

2) open isn't working. (I've already been down this road and switched
another call to an external program to use IPC::Run, but that program
doesn't take long and needs no fork.)
what open()? what's not working? please be more specific, show us some code 
and the actual error messages. Are you talking about open in
http://perl.apache.org/docs/1.0/guide/performance.html#A_Complete_Fork_Example
?

I took out the parts of the code that caused problems and ended up with
this:
   $SIG{CHLD} = 'IGNORE';
   defined (my $pid = fork) or die Cannot fork: $!\n;
   unless ($pid) {
  exec $command;
  CORE::exit(0);
   }
This works and accomplishes my first goal, but not the second. If I start
the program and restart Apache, the program is killed.
have you detached the session as explained here?
http://perl.apache.org/docs/1.0/guide/performance.html#Detaching_the_Forked_Process
I admit I haven't tried this code from the above url with 2.0 yet (and it'd be 
nice to have such a test (hint! hint!)) but I can't see it in your sample, so 
I assume that you haven't tried it ;)

Also while you are at it, once you figure out all the quirks if you can help 
us porting 
http://perl.apache.org/docs/1.0/guide/performance.html#Forking_and_Executing_Subprocesses_from_mod_perl 
to 2.0 docs that would be very helpful for those coming after you. Thanks.

__
Stas BekmanJAm_pH -- Just Another mod_perl Hacker
http://stason.org/ mod_perl Guide --- http://perl.apache.org
mailto:[EMAIL PROTECTED] http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com


Re: mod_perl v2 Forking

2003-09-16 Thread Eric Frazier
Hi,

I guess this is off topic for this list, since I would be doing this no
matter if I was running CGI or mod_perl or whatever. I am pretty desparate
to get this working, and if anyone wants to earn some cash helping me fix
things PLEASE call me at 250 655-9513. 

I have been trying to accomplish the same thing as Cameron, but with the
detaching stuff it seemed a lot easier to make a server with IO::Select and
not actually start the server from mod_perl. The end result hopefully will
be a web user being able to start some things that take time, but not screw
things up by interrupting them. 

But then I found I was using 5.8.. Thanks to a guy on comp.lang.perl.misc I
know that there is a change in how signals are handled, they call it
deferred signal handling because Perl now is suppose to wait until the
Interpeter is in a safe state. As I understand it this might avoid some
things like core dumps or other errors related to dieing while trying to do
something besides dieing. 

The thing is somehow this ends up killing off my parent process, just like
in this post:

http://www.mail-archive.com/[EMAIL PROTECTED]/msg43989.html

So this is happening to me as well, however the guy in the above example had
his problem solved by using Errno and looking for EINTR if that error is
raised then catch it and move on, 

I did get one maybe helpfull thing from my log:

Erro was  %! 
./franken_socket.pl 8607: got - CHLD
 at Tue Sep 16 02:17:42 2003
I got forked
./franken_socket.pl 8599: begat 8607 at Tue Sep 16 02:17:40 2003
begat 8607
./franken_socket.pl 8599: got - CHLD
 at Tue Sep 16 02:17:54 2003
./franken_socket.pl 8599: main 8607 -- reaped 1 at Tue Sep 16 02:17:54 2003
reaped 1Erro was No child processes %! 

So it looks like the parent got killed on that  error No child process 
This code works just fine on 5.6 since it is about 150% from examples :) 
The above is the result of connecting, doing a who, and doing dienow to
test the alarm. 

I also found this: 

http://archive.develooper.com/[EMAIL PROTECTED]/msg03022.html

Which totaly describes my problem as well, but shows it happening with perl
5.8.1.. 


I'd imagine that your accept() isn't being restarted.  How does it work
if you change the loop to look like this?

use Errno;

while (1) {
  my $client = $server-accept or do {
   next if $!{EINTR};
last;
  };
  spawn(\function, whatever);
}

#!/usr/bin/perl -w

## new frankenstein!

  use strict;
  use POSIX ();
  use POSIX 'WNOHANG';
  use Errno;
  use IO::Socket;
  use FindBin ();
  use File::Basename ();
  use File::Spec::Functions;
  use Net::hostent;
  use Carp;
 

  $|=1;
  my $pid;

open (DIED, /var/log/daemon_log) or warn $!;
sub logmsg { print DIED $0 $$: @_ at , scalar localtime, \n }

my $listen_socket = IO::Socket::INET-new(LocalPort = 1081,
LocalAddr = '127.0.0.1',
Proto = 'tcp',
Listen= SOMAXCONN,
Reuse = 1 )
or die can make a tcp server on port 1080 $!;


  # make the daemon cross-platform, so exec always calls the script
  # itself with the right path, no matter how the script was invoked.
  my $script = File::Basename::basename($0);
  my $SELF = catfile $FindBin::Bin, $script;
  # POSIX unmasks the sigprocmask properly
  my $sigset = POSIX::SigSet-new();
  my $action = POSIX::SigAction-new('sigHUP_handler',
 $sigset,
 POSIX::SA_NODEFER);
  my $action_alrm = POSIX::SigAction-new('sigALRM_handler',
 $sigset,
 POSIX::SA_NODEFER);


  POSIX::sigaction(POSIX::SIGHUP, $action);
 POSIX::sigaction(POSIX::SIGALRM, $action_alrm);

  sub sigHUP_handler {
  print got SIGHUP\n;
  exec($SELF, @ARGV) or die Couldn't restart: $!\n;
  }
  sub sigALRM_handler {
  print got ALARM timeout\n;

  }

  $SIG{CHLD} = \REAPER_NEW;

  sub REAPER {
$SIG{CHLD} = \REAPER;  # loathe sysV
my $waitedpid = wait;
logmsg reaped $waitedpid . ($? ?  with exit $? : '');
}

sub REAPER_NEW {
logmsg got - @_\n;
my $wpid = undef;
while ($wpid = waitpid(-1,WNOHANG)0) {

logmsg main $pid -- reaped $wpid . ($? ?  with exit $? : '')
;
print DIED reaped $wpid . ($? ?  with exit $? : '');

}
}


   print PID: $$\n;
   print ARGV: @ARGV\n;
   print [Server $0 accepting clients]\n;

#while (my $connection = $listen_socket-accept()) {
while (1) {
  my $connection = $listen_socket-accept() or do {
next if $!{EINTR};
last;
  };

print DIED Erro was $! %! \n;
$connection-autoflush(1); ## missing seemed to cause client problem, but
not telnet

if (!defined($pid = fork)) {
logmsg cannot fork: $!;

}elsif 

Re: mod_perl v2 Forking

2003-09-16 Thread Rafael Garcia-Suarez
Eric Frazier wrote:
...
 But then I found I was using 5.8.. Thanks to a guy on comp.lang.perl.misc I
 know that there is a change in how signals are handled, they call it
 deferred signal handling because Perl now is suppose to wait until the
 Interpeter is in a safe state. As I understand it this might avoid some
 things like core dumps or other errors related to dieing while trying to do
 something besides dieing. 

Mostly, yes. Look at the perldelta manpage that is distributed with perl
5.8.0, section Safe Signals.

If you want to restore the 5.6-ish unsafe signal handling, this is not
possible with 5.8.0 :(. But, as it has been acknowledged that this unsafe
behaviour is desirable in some cases, it will be possible with perl
5.8.1.

You can grab a 5.8.1 release candidate 4 from CPAN :
http://search.cpan.org/~jhi/
(RC5 should be out in a few days)
and see with it if using unsafe signal handlers solves your problem.
You can enable them with the PERL_SIGNALS environment variable.
Here's the relevant part of the perlrun manpage that comes with perl
5.8.1 RC4 :

=item PERL_SIGNALS

In Perls 5.8.1 and later.  If set to Cunsafe the pre-Perl-5.8.0
signals behaviour (immediate but unsafe) is restored.  If set to
Csafe the safe (or deferred) signals are used.
See Lperlipc/Deferred Signals (Safe signals).

HTH.


RE: mod_perl v2 Forking

2003-09-16 Thread Stephen Hardisty
Hi,
I had a problem with 5.8.1 and forking in that I was either getting zombies using the 
5.6 examples or the parent was dying, depending on which example was used. The way 
round I found was to:

# ignore the child, good rule for life
$SIG{CHLD} = 'IGNORE';

# then sort out the socket
my $server = new IO::Socket::INET(LocalPort = $port,
  Type = SOCK_STREAM,
  Proto = tcp,
  Listen = 5)
or die some error;

# wait for a connection
while(my $client = $server-accept())
{
my $pid = fork;
die Error. Fork: $!\n unless defined $pid;

if($pid == 0)
{
# all your child code here

# when it's done, kill the child:
exit(0);
}
}

This seemes reasonably stable. If anybody has a better way, then I'm all ears.

Cheers!

-Original Message-
From: Eric Frazier [mailto:[EMAIL PROTECTED]
Sent: 16 September 2003 12:24
To: [EMAIL PROTECTED]
Cc: [EMAIL PROTECTED]
Subject: Re: mod_perl v2 Forking


Hi,

I guess this is off topic for this list, since I would be doing this no
matter if I was running CGI or mod_perl or whatever. I am pretty desparate
to get this working, and if anyone wants to earn some cash helping me fix
things PLEASE call me at 250 655-9513. 

I have been trying to accomplish the same thing as Cameron, but with the
detaching stuff it seemed a lot easier to make a server with IO::Select and
not actually start the server from mod_perl. The end result hopefully will
be a web user being able to start some things that take time, but not screw
things up by interrupting them. 

But then I found I was using 5.8.. Thanks to a guy on comp.lang.perl.misc I
know that there is a change in how signals are handled, they call it
deferred signal handling because Perl now is suppose to wait until the
Interpeter is in a safe state. As I understand it this might avoid some
things like core dumps or other errors related to dieing while trying to do
something besides dieing. 

The thing is somehow this ends up killing off my parent process, just like
in this post:

http://www.mail-archive.com/[EMAIL PROTECTED]/msg43989.html

So this is happening to me as well, however the guy in the above example had
his problem solved by using Errno and looking for EINTR if that error is
raised then catch it and move on, 

I did get one maybe helpfull thing from my log:

Erro was  %! 
./franken_socket.pl 8607: got - CHLD
 at Tue Sep 16 02:17:42 2003
I got forked
./franken_socket.pl 8599: begat 8607 at Tue Sep 16 02:17:40 2003
begat 8607
./franken_socket.pl 8599: got - CHLD
 at Tue Sep 16 02:17:54 2003
./franken_socket.pl 8599: main 8607 -- reaped 1 at Tue Sep 16 02:17:54 2003
reaped 1Erro was No child processes %! 

So it looks like the parent got killed on that  error No child process 
This code works just fine on 5.6 since it is about 150% from examples :) 
The above is the result of connecting, doing a who, and doing dienow to
test the alarm. 

I also found this: 

http://archive.develooper.com/[EMAIL PROTECTED]/msg03022.html

Which totaly describes my problem as well, but shows it happening with perl
5.8.1.. 


I'd imagine that your accept() isn't being restarted.  How does it work
if you change the loop to look like this?

use Errno;

while (1) {
  my $client = $server-accept or do {
   next if $!{EINTR};
last;
  };
  spawn(\function, whatever);
}

#!/usr/bin/perl -w

## new frankenstein!

  use strict;
  use POSIX ();
  use POSIX 'WNOHANG';
  use Errno;
  use IO::Socket;
  use FindBin ();
  use File::Basename ();
  use File::Spec::Functions;
  use Net::hostent;
  use Carp;
 

  $|=1;
  my $pid;

open (DIED, /var/log/daemon_log) or warn $!;
sub logmsg { print DIED $0 $$: @_ at , scalar localtime, \n }

my $listen_socket = IO::Socket::INET-new(LocalPort = 1081,
LocalAddr = '127.0.0.1',
Proto = 'tcp',
Listen= SOMAXCONN,
Reuse = 1 )
or die can make a tcp server on port 1080 $!;


  # make the daemon cross-platform, so exec always calls the script
  # itself with the right path, no matter how the script was invoked.
  my $script = File::Basename::basename($0);
  my $SELF = catfile $FindBin::Bin, $script;
  # POSIX unmasks the sigprocmask properly
  my $sigset = POSIX::SigSet-new();
  my $action = POSIX::SigAction-new('sigHUP_handler',
 $sigset,
 POSIX::SA_NODEFER);
  my $action_alrm = POSIX::SigAction-new('sigALRM_handler',
 $sigset,
 POSIX::SA_NODEFER);


  POSIX::sigaction(POSIX::SIGHUP, $action);
 POSIX::sigaction(POSIX::SIGALRM, $action_alrm);

  sub sigHUP_handler {
  print got SIGHUP\n;
  exec($SELF, @ARGV

Re: mod_perl v2 Forking

2003-09-16 Thread Eric Frazier
Hi,

That sound like one way to go, I want to be very careful with something like
this. You speak as if restoring 5.6 behaviour is the best or only way to go.
Do you see any other alternatives? 

Thanks,

Eric 

At 04:57 PM 9/16/03 +0200, Rafael Garcia-Suarez wrote:
Eric Frazier wrote:
...
 But then I found I was using 5.8.. Thanks to a guy on comp.lang.perl.misc I
 know that there is a change in how signals are handled, they call it
 deferred signal handling because Perl now is suppose to wait until the
 Interpeter is in a safe state. As I understand it this might avoid some
 things like core dumps or other errors related to dieing while trying to do
 something besides dieing. 

Mostly, yes. Look at the perldelta manpage that is distributed with perl
5.8.0, section Safe Signals.

I did read that, it seems kind of misleading. The 5.8 IPC doc was more
helpful, but I still didn't get a clear idea how to handle this and the
examples are not updated yet.



If you want to restore the 5.6-ish unsafe signal handling, this is not
possible with 5.8.0 :(. But, as it has been acknowledged that this unsafe
behaviour is desirable in some cases, it will be possible with perl
5.8.1.

You can grab a 5.8.1 release candidate 4 from CPAN :
http://search.cpan.org/~jhi/
(RC5 should be out in a few days)
and see with it if using unsafe signal handlers solves your problem.
You can enable them with the PERL_SIGNALS environment variable.
Here's the relevant part of the perlrun manpage that comes with perl
5.8.1 RC4 :

=item PERL_SIGNALS

In Perls 5.8.1 and later.  If set to Cunsafe the pre-Perl-5.8.0
signals behaviour (immediate but unsafe) is restored.  If set to
Csafe the safe (or deferred) signals are used.
See Lperlipc/Deferred Signals (Safe signals).

HTH.


(250) 655 - 9513 (PST Time Zone)

Inquiry is fatal to certainty. -- Will Durant 






RE: mod_perl v2 Forking

2003-09-16 Thread Eric Frazier
Hi,

Doing this works for me. But I am ending up with some errors that I didn't
have before. Of course my bosses would get mad if I posted all of the code
involed, but basicly a database connection that was working fine is now
returning mysql server has gone away, meaning that the connection got
killed. What is weird/scary, is that if I change your $SIG{CHLD} = 'IGNORE';
back to the handler I was using, the database error goes away, but I am back
were I was. Fun huh? :) 

Thanks,

Eric 

At 03:57 PM 9/16/03 +0100, Stephen Hardisty wrote:
Hi,
I had a problem with 5.8.1 and forking in that I was either getting zombies
using the 5.6 examples or the parent was dying, depending on which example
was used. The way round I found was to:

# ignore the child, good rule for life
$SIG{CHLD} = 'IGNORE';

# then sort out the socket
my $server = new IO::Socket::INET(LocalPort = $port,
  Type = SOCK_STREAM,
  Proto = tcp,
  Listen = 5)
   or die some error;

# wait for a connection
while(my $client = $server-accept())
{
   my $pid = fork;
   die Error. Fork: $!\n unless defined $pid;

   if($pid == 0)
   {
   # all your child code here

   # when it's done, kill the child:
   exit(0);
   }
}

This seemes reasonably stable. If anybody has a better way, then I'm all ears.

Cheers!

-Original Message-
From: Eric Frazier [mailto:[EMAIL PROTECTED]
Sent: 16 September 2003 12:24
To: [EMAIL PROTECTED]
Cc: [EMAIL PROTECTED]
Subject: Re: mod_perl v2 Forking


Hi,

I guess this is off topic for this list, since I would be doing this no
matter if I was running CGI or mod_perl or whatever. I am pretty desparate
to get this working, and if anyone wants to earn some cash helping me fix
things PLEASE call me at 250 655-9513. 

I have been trying to accomplish the same thing as Cameron, but with the
detaching stuff it seemed a lot easier to make a server with IO::Select and
not actually start the server from mod_perl. The end result hopefully will
be a web user being able to start some things that take time, but not screw
things up by interrupting them. 

But then I found I was using 5.8.. Thanks to a guy on comp.lang.perl.misc I
know that there is a change in how signals are handled, they call it
deferred signal handling because Perl now is suppose to wait until the
Interpeter is in a safe state. As I understand it this might avoid some
things like core dumps or other errors related to dieing while trying to do
something besides dieing. 

The thing is somehow this ends up killing off my parent process, just like
in this post:

http://www.mail-archive.com/[EMAIL PROTECTED]/msg43989.html

So this is happening to me as well, however the guy in the above example had
his problem solved by using Errno and looking for EINTR if that error is
raised then catch it and move on, 

I did get one maybe helpfull thing from my log:

Erro was  %! 
./franken_socket.pl 8607: got - CHLD
 at Tue Sep 16 02:17:42 2003
I got forked
./franken_socket.pl 8599: begat 8607 at Tue Sep 16 02:17:40 2003
begat 8607
./franken_socket.pl 8599: got - CHLD
 at Tue Sep 16 02:17:54 2003
./franken_socket.pl 8599: main 8607 -- reaped 1 at Tue Sep 16 02:17:54 2003
reaped 1Erro was No child processes %! 

So it looks like the parent got killed on that  error No child process 
This code works just fine on 5.6 since it is about 150% from examples :) 
The above is the result of connecting, doing a who, and doing dienow to
test the alarm. 

I also found this: 

http://archive.develooper.com/[EMAIL PROTECTED]/msg03022.html

Which totaly describes my problem as well, but shows it happening with perl
5.8.1.. 


I'd imagine that your accept() isn't being restarted.  How does it work
if you change the loop to look like this?

use Errno;

while (1) {
  my $client = $server-accept or do {
   next if $!{EINTR};
last;
  };
  spawn(\function, whatever);
}

#!/usr/bin/perl -w

## new frankenstein!

  use strict;
  use POSIX ();
  use POSIX 'WNOHANG';
  use Errno;
  use IO::Socket;
  use FindBin ();
  use File::Basename ();
  use File::Spec::Functions;
  use Net::hostent;
  use Carp;
 

  $|=1;
  my $pid;

open (DIED, /var/log/daemon_log) or warn $!;
sub logmsg { print DIED $0 $$: @_ at , scalar localtime, \n }

my $listen_socket = IO::Socket::INET-new(LocalPort = 1081,
LocalAddr = '127.0.0.1',
Proto = 'tcp',
Listen= SOMAXCONN,
Reuse = 1 )
or die can make a tcp server on port 1080 $!;


  # make the daemon cross-platform, so exec always calls the script
  # itself with the right path, no matter how the script was invoked.
  my $script = File::Basename::basename($0);
  my $SELF = catfile $FindBin::Bin, $script;
  # POSIX unmasks the sigprocmask

RE: mod_perl v2 Forking

2003-09-16 Thread Stephen Hardisty
Hi,
is the database connection created in the child or before it?
If it's created inside the child then it'll die ungracefully when the child
dies, so put something nice and fluffy to close it before the exit.
Otherwise, I don't know I'm afraid.

-Original Message-
From: Eric Frazier [mailto:[EMAIL PROTECTED]
Sent: 16 September 2003 12:57
To: Stephen Hardisty
Cc: [EMAIL PROTECTED]
Subject: RE: mod_perl v2 Forking


Hi,

Doing this works for me. But I am ending up with some errors that I didn't
have before. Of course my bosses would get mad if I posted all of the code
involed, but basicly a database connection that was working fine is now
returning mysql server has gone away, meaning that the connection got
killed. What is weird/scary, is that if I change your $SIG{CHLD} = 'IGNORE';
back to the handler I was using, the database error goes away, but I am back
were I was. Fun huh? :) 

Thanks,

Eric 

At 03:57 PM 9/16/03 +0100, Stephen Hardisty wrote:
Hi,
I had a problem with 5.8.1 and forking in that I was either getting zombies
using the 5.6 examples or the parent was dying, depending on which example
was used. The way round I found was to:

# ignore the child, good rule for life
$SIG{CHLD} = 'IGNORE';

# then sort out the socket
my $server = new IO::Socket::INET(LocalPort = $port,
  Type = SOCK_STREAM,
  Proto = tcp,
  Listen = 5)
   or die some error;

# wait for a connection
while(my $client = $server-accept())
{
   my $pid = fork;
   die Error. Fork: $!\n unless defined $pid;

   if($pid == 0)
   {
   # all your child code here

   # when it's done, kill the child:
   exit(0);
   }
}

This seemes reasonably stable. If anybody has a better way, then I'm all ears.

Cheers!

-Original Message-
From: Eric Frazier [mailto:[EMAIL PROTECTED]
Sent: 16 September 2003 12:24
To: [EMAIL PROTECTED]
Cc: [EMAIL PROTECTED]
Subject: Re: mod_perl v2 Forking


Hi,

I guess this is off topic for this list, since I would be doing this no
matter if I was running CGI or mod_perl or whatever. I am pretty desparate
to get this working, and if anyone wants to earn some cash helping me fix
things PLEASE call me at 250 655-9513. 

I have been trying to accomplish the same thing as Cameron, but with the
detaching stuff it seemed a lot easier to make a server with IO::Select and
not actually start the server from mod_perl. The end result hopefully will
be a web user being able to start some things that take time, but not screw
things up by interrupting them. 

But then I found I was using 5.8.. Thanks to a guy on comp.lang.perl.misc I
know that there is a change in how signals are handled, they call it
deferred signal handling because Perl now is suppose to wait until the
Interpeter is in a safe state. As I understand it this might avoid some
things like core dumps or other errors related to dieing while trying to do
something besides dieing. 

The thing is somehow this ends up killing off my parent process, just like
in this post:

http://www.mail-archive.com/[EMAIL PROTECTED]/msg43989.html

So this is happening to me as well, however the guy in the above example had
his problem solved by using Errno and looking for EINTR if that error is
raised then catch it and move on, 

I did get one maybe helpfull thing from my log:

Erro was  %! 
./franken_socket.pl 8607: got - CHLD
 at Tue Sep 16 02:17:42 2003
I got forked
./franken_socket.pl 8599: begat 8607 at Tue Sep 16 02:17:40 2003
begat 8607
./franken_socket.pl 8599: got - CHLD
 at Tue Sep 16 02:17:54 2003
./franken_socket.pl 8599: main 8607 -- reaped 1 at Tue Sep 16 02:17:54 2003
reaped 1Erro was No child processes %! 

So it looks like the parent got killed on that  error No child process 
This code works just fine on 5.6 since it is about 150% from examples :) 
The above is the result of connecting, doing a who, and doing dienow to
test the alarm. 

I also found this: 

http://archive.develooper.com/[EMAIL PROTECTED]/msg03022.html

Which totaly describes my problem as well, but shows it happening with perl
5.8.1.. 


I'd imagine that your accept() isn't being restarted.  How does it work
if you change the loop to look like this?

use Errno;

while (1) {
  my $client = $server-accept or do {
   next if $!{EINTR};
last;
  };
  spawn(\function, whatever);
}

#!/usr/bin/perl -w

## new frankenstein!

  use strict;
  use POSIX ();
  use POSIX 'WNOHANG';
  use Errno;
  use IO::Socket;
  use FindBin ();
  use File::Basename ();
  use File::Spec::Functions;
  use Net::hostent;
  use Carp;
 

  $|=1;
  my $pid;

open (DIED, /var/log/daemon_log) or warn $!;
sub logmsg { print DIED $0 $$: @_ at , scalar localtime, \n }

my $listen_socket = IO::Socket::INET-new(LocalPort = 1081,
LocalAddr = '127.0.0.1',
Proto

RE: mod_perl v2 Forking

2003-09-16 Thread Eric Frazier
Hi,

Well, I am not sure if this is going to be the best solution long term, but
it works!

 while ( $connection ){

my $return_value = undef;

if(/quit|exit/i){ last;}
elsif (/closeme/i ) {$connection-close(); }
elsif (/date|time/i){ printf $connection %s\n, scalar
localtime; exit(0);  }

that did call to a sub, and then connected to a database. I am wondering if
that connection object is better off being global. I changed the connect to
be global, restarted and did a test and it worked fine! I was all ready to
post back to here with the good news, when just to double check I went back
and made the db connect in the local sub like before. And it still worked?!
So it seems like I might be in better shape for now, but I might have some
long term problems with DB connections dieing, most likely related to this
child handling. I have to think that becase the query I am doing is VERY
well tested and never causes an issue. 

Thanks tremedously for everyone's help so far, I at the very least have some
directions to go in now.

I still would very much like to learn what the correct, put it in the book
solution should be.. 


Eric 




At 03:57 PM 9/16/03 +0100, Stephen Hardisty wrote:
Hi,
I had a problem with 5.8.1 and forking in that I was either getting zombies
using the 5.6 examples or the parent was dying, depending on which example
was used. The way round I found was to:

# ignore the child, good rule for life
$SIG{CHLD} = 'IGNORE';

# then sort out the socket
my $server = new IO::Socket::INET(LocalPort = $port,
  Type = SOCK_STREAM,
  Proto = tcp,
  Listen = 5)
   or die some error;

# wait for a connection
while(my $client = $server-accept())
{
   my $pid = fork;
   die Error. Fork: $!\n unless defined $pid;

   if($pid == 0)
   {
   # all your child code here

   # when it's done, kill the child:
   exit(0);
   }
}

This seemes reasonably stable. If anybody has a better way, then I'm all ears.

Cheers!

-Original Message-
From: Eric Frazier [mailto:[EMAIL PROTECTED]
Sent: 16 September 2003 12:24
To: [EMAIL PROTECTED]
Cc: [EMAIL PROTECTED]
Subject: Re: mod_perl v2 Forking


Hi,

I guess this is off topic for this list, since I would be doing this no
matter if I was running CGI or mod_perl or whatever. I am pretty desparate
to get this working, and if anyone wants to earn some cash helping me fix
things PLEASE call me at 250 655-9513. 

I have been trying to accomplish the same thing as Cameron, but with the
detaching stuff it seemed a lot easier to make a server with IO::Select and
not actually start the server from mod_perl. The end result hopefully will
be a web user being able to start some things that take time, but not screw
things up by interrupting them. 

But then I found I was using 5.8.. Thanks to a guy on comp.lang.perl.misc I
know that there is a change in how signals are handled, they call it
deferred signal handling because Perl now is suppose to wait until the
Interpeter is in a safe state. As I understand it this might avoid some
things like core dumps or other errors related to dieing while trying to do
something besides dieing. 

The thing is somehow this ends up killing off my parent process, just like
in this post:

http://www.mail-archive.com/[EMAIL PROTECTED]/msg43989.html

So this is happening to me as well, however the guy in the above example had
his problem solved by using Errno and looking for EINTR if that error is
raised then catch it and move on, 

I did get one maybe helpfull thing from my log:

Erro was  %! 
./franken_socket.pl 8607: got - CHLD
 at Tue Sep 16 02:17:42 2003
I got forked
./franken_socket.pl 8599: begat 8607 at Tue Sep 16 02:17:40 2003
begat 8607
./franken_socket.pl 8599: got - CHLD
 at Tue Sep 16 02:17:54 2003
./franken_socket.pl 8599: main 8607 -- reaped 1 at Tue Sep 16 02:17:54 2003
reaped 1Erro was No child processes %! 

So it looks like the parent got killed on that  error No child process 
This code works just fine on 5.6 since it is about 150% from examples :) 
The above is the result of connecting, doing a who, and doing dienow to
test the alarm. 

I also found this: 

http://archive.develooper.com/[EMAIL PROTECTED]/msg03022.html

Which totaly describes my problem as well, but shows it happening with perl
5.8.1.. 


I'd imagine that your accept() isn't being restarted.  How does it work
if you change the loop to look like this?

use Errno;

while (1) {
  my $client = $server-accept or do {
   next if $!{EINTR};
last;
  };
  spawn(\function, whatever);
}

#!/usr/bin/perl -w

## new frankenstein!

  use strict;
  use POSIX ();
  use POSIX 'WNOHANG';
  use Errno;
  use IO::Socket;
  use FindBin ();
  use File::Basename

RE: mod_perl v2 Forking

2003-09-16 Thread Eric Frazier
:) I think that makes sense. It was created in the child.  It seemed to be
fixed when I made the connection global. When I tried the connection in the
child again it might well have been a lucky transpireing of events that let
the child stay alive long enough for the query to get completed. So I should
keep it global I think. 

Thanks,

Eric 

At 04:24 PM 9/16/03 +0100, Stephen Hardisty wrote:
Hi,
is the database connection created in the child or before it?
If it's created inside the child then it'll die ungracefully when the child
dies, so put something nice and fluffy to close it before the exit.
Otherwise, I don't know I'm afraid.

-Original Message-
From: Eric Frazier [mailto:[EMAIL PROTECTED]
Sent: 16 September 2003 12:57
To: Stephen Hardisty
Cc: [EMAIL PROTECTED]
Subject: RE: mod_perl v2 Forking


Hi,

Doing this works for me. But I am ending up with some errors that I didn't
have before. Of course my bosses would get mad if I posted all of the code
involed, but basicly a database connection that was working fine is now
returning mysql server has gone away, meaning that the connection got
killed. What is weird/scary, is that if I change your $SIG{CHLD} = 'IGNORE';
back to the handler I was using, the database error goes away, but I am back
were I was. Fun huh? :) 

Thanks,

Eric 

At 03:57 PM 9/16/03 +0100, Stephen Hardisty wrote:
Hi,
I had a problem with 5.8.1 and forking in that I was either getting zombies
using the 5.6 examples or the parent was dying, depending on which example
was used. The way round I found was to:

# ignore the child, good rule for life
$SIG{CHLD} = 'IGNORE';

# then sort out the socket
my $server = new IO::Socket::INET(LocalPort = $port,
  Type = SOCK_STREAM,
  Proto = tcp,
  Listen = 5)
  or die some error;

# wait for a connection
while(my $client = $server-accept())
{
  my $pid = fork;
  die Error. Fork: $!\n unless defined $pid;

  if($pid == 0)
  {
  # all your child code here

  # when it's done, kill the child:
  exit(0);
  }
}

This seemes reasonably stable. If anybody has a better way, then I'm all ears.

Cheers!

-Original Message-
From: Eric Frazier [mailto:[EMAIL PROTECTED]
Sent: 16 September 2003 12:24
To: [EMAIL PROTECTED]
Cc: [EMAIL PROTECTED]
Subject: Re: mod_perl v2 Forking


Hi,

I guess this is off topic for this list, since I would be doing this no
matter if I was running CGI or mod_perl or whatever. I am pretty desparate
to get this working, and if anyone wants to earn some cash helping me fix
things PLEASE call me at 250 655-9513. 

I have been trying to accomplish the same thing as Cameron, but with the
detaching stuff it seemed a lot easier to make a server with IO::Select and
not actually start the server from mod_perl. The end result hopefully will
be a web user being able to start some things that take time, but not screw
things up by interrupting them. 

But then I found I was using 5.8.. Thanks to a guy on comp.lang.perl.misc I
know that there is a change in how signals are handled, they call it
deferred signal handling because Perl now is suppose to wait until the
Interpeter is in a safe state. As I understand it this might avoid some
things like core dumps or other errors related to dieing while trying to do
something besides dieing. 

The thing is somehow this ends up killing off my parent process, just like
in this post:

http://www.mail-archive.com/[EMAIL PROTECTED]/msg43989.html

So this is happening to me as well, however the guy in the above example had
his problem solved by using Errno and looking for EINTR if that error is
raised then catch it and move on, 

I did get one maybe helpfull thing from my log:

Erro was  %! 
./franken_socket.pl 8607: got - CHLD
 at Tue Sep 16 02:17:42 2003
I got forked
./franken_socket.pl 8599: begat 8607 at Tue Sep 16 02:17:40 2003
begat 8607
./franken_socket.pl 8599: got - CHLD
 at Tue Sep 16 02:17:54 2003
./franken_socket.pl 8599: main 8607 -- reaped 1 at Tue Sep 16 02:17:54 2003
reaped 1Erro was No child processes %! 

So it looks like the parent got killed on that  error No child process 
This code works just fine on 5.6 since it is about 150% from examples :) 
The above is the result of connecting, doing a who, and doing dienow to
test the alarm. 

I also found this: 

http://archive.develooper.com/[EMAIL PROTECTED]/msg03022.html

Which totaly describes my problem as well, but shows it happening with perl
5.8.1.. 


I'd imagine that your accept() isn't being restarted.  How does it work
if you change the loop to look like this?

use Errno;

while (1) {
  my $client = $server-accept or do {
   next if $!{EINTR};
last;
  };
  spawn(\function, whatever);
}

#!/usr/bin/perl -w

## new frankenstein!

  use strict;
  use POSIX ();
  use POSIX 'WNOHANG';
  use Errno;
  use IO::Socket

RE: mod_perl v2 Forking

2003-09-16 Thread Gareth Kirwan
Haven't read much of this thread, but is POE an option ?

 -Original Message-
 From: Eric Frazier [mailto:[EMAIL PROTECTED]
 Sent: 16 September 2003 13:17
 To: Stephen Hardisty
 Cc: [EMAIL PROTECTED]
 Subject: RE: mod_perl v2 Forking
 
 
 :) I think that makes sense. It was created in the child.  It 
 seemed to be
 fixed when I made the connection global. When I tried the 
 connection in the
 child again it might well have been a lucky transpireing of 
 events that let
 the child stay alive long enough for the query to get 
 completed. So I should
 keep it global I think. 
 
 Thanks,
 
 Eric 
 
 At 04:24 PM 9/16/03 +0100, Stephen Hardisty wrote:
 Hi,
 is the database connection created in the child or before it?
 If it's created inside the child then it'll die ungracefully 
 when the child
 dies, so put something nice and fluffy to close it before the exit.
 Otherwise, I don't know I'm afraid.
 
 -Original Message-
 From: Eric Frazier [mailto:[EMAIL PROTECTED]
 Sent: 16 September 2003 12:57
 To: Stephen Hardisty
 Cc: [EMAIL PROTECTED]
 Subject: RE: mod_perl v2 Forking
 
 
 Hi,
 
 Doing this works for me. But I am ending up with some 
 errors that I didn't
 have before. Of course my bosses would get mad if I posted 
 all of the code
 involed, but basicly a database connection that was working 
 fine is now
 returning mysql server has gone away, meaning that the 
 connection got
 killed. What is weird/scary, is that if I change your 
 $SIG{CHLD} = 'IGNORE';
 back to the handler I was using, the database error goes 
 away, but I am back
 were I was. Fun huh? :) 
 
 Thanks,
 
 Eric 
 
 At 03:57 PM 9/16/03 +0100, Stephen Hardisty wrote:
 Hi,
 I had a problem with 5.8.1 and forking in that I was either 
 getting zombies
 using the 5.6 examples or the parent was dying, depending on 
 which example
 was used. The way round I found was to:
 
 # ignore the child, good rule for life
 $SIG{CHLD} = 'IGNORE';
 
 # then sort out the socket
 my $server = new IO::Socket::INET(LocalPort = $port,
   Type = SOCK_STREAM,
   Proto = tcp,
   Listen = 5)
 or die some error;
 
 # wait for a connection
 while(my $client = $server-accept())
 {
 my $pid = fork;
 die Error. Fork: $!\n unless defined $pid;
 
 if($pid == 0)
 {
 # all your child code here
 
 # when it's done, kill the child:
 exit(0);
 }
 }
 
 This seemes reasonably stable. If anybody has a better way, 
 then I'm all ears.
 
 Cheers!
 
 -Original Message-
 From: Eric Frazier [mailto:[EMAIL PROTECTED]
 Sent: 16 September 2003 12:24
 To: [EMAIL PROTECTED]
 Cc: [EMAIL PROTECTED]
 Subject: Re: mod_perl v2 Forking
 
 
 Hi,
 
 I guess this is off topic for this list, since I would be 
 doing this no
 matter if I was running CGI or mod_perl or whatever. I am 
 pretty desparate
 to get this working, and if anyone wants to earn some cash 
 helping me fix
 things PLEASE call me at 250 655-9513. 
 
 I have been trying to accomplish the same thing as Cameron, 
 but with the
 detaching stuff it seemed a lot easier to make a server 
 with IO::Select and
 not actually start the server from mod_perl. The end result 
 hopefully will
 be a web user being able to start some things that take 
 time, but not screw
 things up by interrupting them. 
 
 But then I found I was using 5.8.. Thanks to a guy on 
 comp.lang.perl.misc I
 know that there is a change in how signals are handled, they call it
 deferred signal handling because Perl now is suppose to 
 wait until the
 Interpeter is in a safe state. As I understand it this 
 might avoid some
 things like core dumps or other errors related to dieing 
 while trying to do
 something besides dieing. 
 
 The thing is somehow this ends up killing off my parent 
 process, just like
 in this post:
 
 http://www.mail-archive.com/[EMAIL PROTECTED]/msg43989.html
 
 So this is happening to me as well, however the guy in the 
 above example had
 his problem solved by using Errno and looking for EINTR if 
 that error is
 raised then catch it and move on, 
 
 I did get one maybe helpfull thing from my log:
 
 Erro was  %! 
 ./franken_socket.pl 8607: got - CHLD
  at Tue Sep 16 02:17:42 2003
 I got forked
 ./franken_socket.pl 8599: begat 8607 at Tue Sep 16 02:17:40 2003
 begat 8607
 ./franken_socket.pl 8599: got - CHLD
  at Tue Sep 16 02:17:54 2003
 ./franken_socket.pl 8599: main 8607 -- reaped 1 at Tue Sep 
 16 02:17:54 2003
 reaped 1Erro was No child processes %! 
 
 So it looks like the parent got killed on that  error No 
 child process 
 This code works just fine on 5.6 since it is about 150% 
 from examples :) 
 The above is the result of connecting, doing a who, and 
 doing dienow to
 test the alarm. 
 
 I also found this: 
 
 http://archive.develooper.com/[EMAIL PROTECTED]/msg03022.html
 
 Which totaly describes my problem as well, but shows

RE: mod_perl v2 Forking

2003-09-16 Thread Stephen Hardisty
I guess you could, but if there's already a load of code mightn't be a bit of a pain 
POE-ing it?

-Original Message-
From: Gareth Kirwan [mailto:[EMAIL PROTECTED]
Sent: 16 September 2003 16:50
To: 'Eric Frazier'; Stephen Hardisty
Cc: [EMAIL PROTECTED]
Subject: RE: mod_perl v2 Forking


Haven't read much of this thread, but is POE an option ?

 -Original Message-
 From: Eric Frazier [mailto:[EMAIL PROTECTED]
 Sent: 16 September 2003 13:17
 To: Stephen Hardisty
 Cc: [EMAIL PROTECTED]
 Subject: RE: mod_perl v2 Forking
 
 
 :) I think that makes sense. It was created in the child.  It 
 seemed to be
 fixed when I made the connection global. When I tried the 
 connection in the
 child again it might well have been a lucky transpireing of 
 events that let
 the child stay alive long enough for the query to get 
 completed. So I should
 keep it global I think. 
 
 Thanks,
 
 Eric 
 
 At 04:24 PM 9/16/03 +0100, Stephen Hardisty wrote:
 Hi,
 is the database connection created in the child or before it?
 If it's created inside the child then it'll die ungracefully 
 when the child
 dies, so put something nice and fluffy to close it before the exit.
 Otherwise, I don't know I'm afraid.
 
 -Original Message-
 From: Eric Frazier [mailto:[EMAIL PROTECTED]
 Sent: 16 September 2003 12:57
 To: Stephen Hardisty
 Cc: [EMAIL PROTECTED]
 Subject: RE: mod_perl v2 Forking
 
 
 Hi,
 
 Doing this works for me. But I am ending up with some 
 errors that I didn't
 have before. Of course my bosses would get mad if I posted 
 all of the code
 involed, but basicly a database connection that was working 
 fine is now
 returning mysql server has gone away, meaning that the 
 connection got
 killed. What is weird/scary, is that if I change your 
 $SIG{CHLD} = 'IGNORE';
 back to the handler I was using, the database error goes 
 away, but I am back
 were I was. Fun huh? :) 
 
 Thanks,
 
 Eric 
 
 At 03:57 PM 9/16/03 +0100, Stephen Hardisty wrote:
 Hi,
 I had a problem with 5.8.1 and forking in that I was either 
 getting zombies
 using the 5.6 examples or the parent was dying, depending on 
 which example
 was used. The way round I found was to:
 
 # ignore the child, good rule for life
 $SIG{CHLD} = 'IGNORE';
 
 # then sort out the socket
 my $server = new IO::Socket::INET(LocalPort = $port,
   Type = SOCK_STREAM,
   Proto = tcp,
   Listen = 5)
 or die some error;
 
 # wait for a connection
 while(my $client = $server-accept())
 {
 my $pid = fork;
 die Error. Fork: $!\n unless defined $pid;
 
 if($pid == 0)
 {
 # all your child code here
 
 # when it's done, kill the child:
 exit(0);
 }
 }
 
 This seemes reasonably stable. If anybody has a better way, 
 then I'm all ears.
 
 Cheers!
 
 -Original Message-
 From: Eric Frazier [mailto:[EMAIL PROTECTED]
 Sent: 16 September 2003 12:24
 To: [EMAIL PROTECTED]
 Cc: [EMAIL PROTECTED]
 Subject: Re: mod_perl v2 Forking
 
 
 Hi,
 
 I guess this is off topic for this list, since I would be 
 doing this no
 matter if I was running CGI or mod_perl or whatever. I am 
 pretty desparate
 to get this working, and if anyone wants to earn some cash 
 helping me fix
 things PLEASE call me at 250 655-9513. 
 
 I have been trying to accomplish the same thing as Cameron, 
 but with the
 detaching stuff it seemed a lot easier to make a server 
 with IO::Select and
 not actually start the server from mod_perl. The end result 
 hopefully will
 be a web user being able to start some things that take 
 time, but not screw
 things up by interrupting them. 
 
 But then I found I was using 5.8.. Thanks to a guy on 
 comp.lang.perl.misc I
 know that there is a change in how signals are handled, they call it
 deferred signal handling because Perl now is suppose to 
 wait until the
 Interpeter is in a safe state. As I understand it this 
 might avoid some
 things like core dumps or other errors related to dieing 
 while trying to do
 something besides dieing. 
 
 The thing is somehow this ends up killing off my parent 
 process, just like
 in this post:
 
 http://www.mail-archive.com/[EMAIL PROTECTED]/msg43989.html
 
 So this is happening to me as well, however the guy in the 
 above example had
 his problem solved by using Errno and looking for EINTR if 
 that error is
 raised then catch it and move on, 
 
 I did get one maybe helpfull thing from my log:
 
 Erro was  %! 
 ./franken_socket.pl 8607: got - CHLD
  at Tue Sep 16 02:17:42 2003
 I got forked
 ./franken_socket.pl 8599: begat 8607 at Tue Sep 16 02:17:40 2003
 begat 8607
 ./franken_socket.pl 8599: got - CHLD
  at Tue Sep 16 02:17:54 2003
 ./franken_socket.pl 8599: main 8607 -- reaped 1 at Tue Sep 
 16 02:17:54 2003
 reaped 1Erro was No child processes %! 
 
 So it looks like the parent got killed on that  error No 
 child process 
 This code works

(please trim your followups!) Re: mod_perl v2 Forking

2003-09-16 Thread Stas Bekman
whoah! people, please trim the irrelevant stuff in your replies, this thread 
keeps on growing for no reason. Perhaps you should read
http://perl.apache.org/maillist/email-etiquette.html#Extracts_From_Other_Posts
if you are new to this list. We want these threads to be useful for those who 
will later read them in archives.

Thank you!
__
Stas BekmanJAm_pH -- Just Another mod_perl Hacker
http://stason.org/ mod_perl Guide --- http://perl.apache.org
mailto:[EMAIL PROTECTED] http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com


Re: mod_perl v2 Forking

2003-09-15 Thread Martin Langhoff
Cameron,

Have you tried issuing the command to `at`?  If you don't need to 
interact wih the report generator, and can pass all the parameters in 
the command line or via a tmp file, this is a great solution.

at (and the corresponding atd) will preserve your environment vars and 
other niceties.

regards,





martin



Re: mod_perl v2 Forking

2003-09-12 Thread Gregory S. Youngblood
I've been following this just at a high level, so if I'm posting a method
that you've already tried and dismissed please forgive me.

You can try forking followed by separating from the parent session. I
think that will help keep your program from getting killed when apache is
restarted or stopped.

use POSIX;

# FORK
$pid = fork;
if (not defined $pid) {
  # unable to fork

} elsif ($pid) {
  # parent to exit, child continue
  exit 0;
}

# Separate from parent
$status = 0;
POSIX::setsid() or $status = Couldn't start new session: $!;
if ($status) {
  # unable to separate from parent session

} else {
  # searated from parent
  $status = 0;
}


On Fri, 12 Sep 2003, Cameron B. Prince wrote:

 Hi all...

 Sorry about the previous message getting screwed up... Not sure what
 happened...

 I have a report generator program written in Perl that I need to start from
 a CGI. The program takes about 15 minutes to run, so I must fork or double
 fork. I have two goals:

 1) Have no zombies when the program completes
 2) Fork in such a way that restarting Apache doesn't kill the forked
 process.

 I tried out the code here which is for mod_perl v1:

 http://perl.apache.org/docs/1.0/guide/performance.html#Forking_and_Executing
 _Subprocesses_from_mod_perl

 There are two problems with the code listed in the example:

 1) Apache::SubProcess doesn't seem to contain the same methods as the older
 version.
 2) open isn't working. (I've already been down this road and switched
 another call to an external program to use IPC::Run, but that program
 doesn't take long and needs no fork.)

 I took out the parts of the code that caused problems and ended up with
 this:

$SIG{CHLD} = 'IGNORE';
defined (my $pid = fork) or die Cannot fork: $!\n;
unless ($pid) {
   exec $command;
   CORE::exit(0);
}

 This works and accomplishes my first goal, but not the second. If I start
 the program and restart Apache, the program is killed.

 Does anyone have ideas as to how to solve this?


 Thanks,
 Cameron