The warning from William T. made me think to ask:
Does your site have "KeepAlive On" in httpd.conf?
(If not I can't think of anything to suggest...)
If so, try adding this as part of the redirect:
use Apache2::Connection();
use Apache2::RequestRec();
...
my $c = $r->connection();
$c->keepalive(Apache2::Const::CONN_CLOSE);
This will keep your process (which is about to do a "long"
cleanup) from automatically getting the redirected request
from the browser.
Hopefully the root httpd will know that this "redirecting"
child has not finished the complete cycle, and will launch
other children if needed to process the redirected request
plus any other requests.
Of course William is right that if lots of requests are
arriving that need such cleanup, and the cleanup really does
take a long time on average, you are likely to pile up
more children than your household income (I'm sorry I meant
to say your server :-) can support.
Good Luck,
cmac
On Jan 26, 2010, at 2:27 PM, Tosh Cooey wrote:
> So this works almost perfectly... Almost because:
>
> #!/usr/bin/perl
>
> use strict;
> use Apache2::Const(); # defines OK
> use Apache2::Log(); # defines warn
> use Apache2::RequestUtil(); # defines push_handlers
>
> my $r = shift;
> $r->push_handlers(PerlCleanupHandler => \&cleanup );
>
> $r->headers_out->set(Location => 'http://...index.pl');
> $r->status(Apache2::Const::REDIRECT);
> return Apache2::Const::REDIRECT;
>
> sub cleanup {
> my ($r) = @_;
> $r->warn("Starting cleanup");
> foreach my $num (1..5) {
> $r->warn("Number is $num");
> sleep 2;
> }
> return Apache2::Const::OK;
> }
> ######## test.pl
>
>
> It seems if you take the above program and hit it with Firefox
> (3.5.7 and 3.6) it may take 10 seconds (5 x sleep 2) before Firefox
> does the redirect. Safari 4.0.4 seems fine. curl works as well :)
>
> I said "may" above because it's not consistent. If you launch
> Firefox fresh and hit the above program it may redirect instantly,
> but then subsequent hits will illustrate the delay. I'm also
> seeing varying behaviour on a different server that has no Basic
> Auth, but always the problem is there.
>
> Can anyone else reproduce this?
>
> Thank-you!
>
> Tosh
>
>
> [email protected] wrote:
>> at(1) is a Unix command to start a process.
>> Assuming you're on a Unix/Linux box, type "man at" to get the story.
>> A cleanup handler is more pleasant than a prostate exam.
>> You can spend your life waiting for others. Just write a
>> routine called "cleanup" and have it do something like
>> make a log entry.
>> use Apache2::Const(); # defines OK
>> use Apache2::Log(); # defines warn
>> use Apache2::RequestUtil(); # defines push_handlers
>> ...
>> sub cleanup {
>> my ($r) = @_;
>> $r->warn("cleanup was here");
>> return Apache2::Const::OK;
>> }
>> Then put a call like the one below in your ModPerl::Registry routine.
>> If the log entry shows up in error_log, you're on your way...
>> Good Luck,
>> cmac
>> P.S. Google doesn't index some sites well.
>> Look at http://perl.apache.org/docs/2.0/
>> particularly its API link.
>> On Jan 25, 2010, at 5:49 PM, Tosh Cooey wrote:
>>> Sorry, I couldn't figure out what at(1) meant (or maybe ap(1)
>>> which you say below) is that an abbreviation for something?
>>>
>>> And Perrin saying "cleanup handler" is right up there with
>>> "prostate exam" in my list of things to get into, both scare me!
>>>
>>> Of course at some point a man needs to do both...
>>>
>>> So... If this magic: $r->push_handlers(PerlCleanupHandler =>
>>> \&cleanup); is available in ModPerl::Registry context then I will
>>> attempt to force all my forks into early retirement and work the
>>> problem out that way.
>>>
>>> Unfortunately Google doesn't return an easy answer, anybody know
>>> this before I spend all day tomorrow in my struggle?
>>>
>>> Thank-you all again,
>>>
>>> Tosh
>>>
>>>
>>> [email protected] wrote:
>>>> You made no comment on the links I sent you earlier today.
>>>> They had lots of good advice. Particularly the first one
>>>> suggested not forking the Apache process, but using an
>>>> ap(1) call to start a process to do the additional processing.
>>>> OK, the ap(1) alternative was a bit light on details.
>>>> How about the alternative offered by Perrin Hawkins in the
>>>> same thread, of using a cleanup handler to do the follow-up
>>>> processing rather than a forked process.
>>>> From p. 107 of "mod_per2 User's Guide":
>>>> $r->push_handlers(PerlCleanupHandler => \&cleanup);
>>>>> print $in->redirect... # to redirect the browser
>>>> Now cleanup (which receives $r as its operand) can do
>>>> whatever slow stuff you need to, can probably use DBI
>>>> without all the pain you have below, and can access the
>>>> request to find out what to do.
>>>> In some past context you may have learned how to get hold of
>>>> a $r to use in these calls, and hopefully you're no longer
>>>> scared of $r. But there does remain the question of whether
>>>> a ModPerl::Registry module can do such calls.
>>>> Hopefully someone who knows can chime in on this.
>>>> If not, for me it would be worth the editing of getting the
>>>> module out from under ModPerl::Registry and into the "native
>>>> mode" of SetHandler modperl.
>>>> Best of luck,
>>>> cmac
>>>> On Jan 25, 2010, at 1:54 PM, Tosh Cooey wrote:
>>>>> Ok, then maybe I need to supply some code here to try and get
>>>>> clarification:
>>>>>
>>>>> mailfile.pl
>>>>> ###########
>>>>> use strict;
>>>>> ...
>>>>> use POSIX;
>>>>>
>>>>> #gather needed modules and objects
>>>>> my $fileOBJ = new MyOBJS::FILE($in->param('id'));
>>>>> my $clientOBJ = new ...
>>>>> my $userOBJ = new ...
>>>>> # All OBJjects have a {DBH} property which is their DB handle
>>>>> # I hear I have to disconnect these first, do I have to
>>>>> disconnect ALL?
>>>>> $fileOBJ->{DBH}->disconnect;
>>>>> $SIG{CHLD} = 'IGNORE';
>>>>> my $pid;
>>>>> if ($pid = fork) {
>>>>> warn "Pid = $pid";
>>>>> } elsif (defined $pid) {
>>>>> close(STDOUT);
>>>>> close(STDIN);
>>>>> close(STDERR);
>>>>>
>>>>> # chdir to /, stops the process from preventing an unmount
>>>>> chdir '/' or die "Can't chdir to /: $!";
>>>>> # dump our STDIN and STDOUT handles
>>>>> open STDIN, '/dev/null' or die "Can't read /dev/null: $!";
>>>>> open STDOUT, '>/dev/null' or die "Can't write to /dev/null:
>>>>> $!";
>>>>> # redirect for logging
>>>>> open STDERR, '>/tmp/stderr' or die "Can't write to /tmp/
>>>>> stderr: $!";
>>>>> # Prevent locking to apache process
>>>>> setsid or die "Can't start a new session: $!";
>>>>>
>>>>> # Create file download link email
>>>>> my $mailSTR = ...
>>>>>
>>>>> # Send the mail possibly to many people
>>>>> foreach my $person (@people) {
>>>>> open(MAIL, '|' . &cfg('sendmail_location') . ' -t');
>>>>> print MAIL $mailSTR;
>>>>> close(MAIL);
>>>>> }
>>>>>
>>>>> # Need to recreate the DBI connection on the $fileOBJ I hear
>>>>> $fileOBJ = new MyOBJS::FILE($in->param('id'));
>>>>>
>>>>> # Do some SQL to update the $fileOBJ status based on mailout
>>>>> $fileOBJ->sql....
>>>>>
>>>>> # create LOGGING Objects to log stuff
>>>>> my $logOBJ = new ...
>>>>> $logOBJ->sql...
>>>>>
>>>>> CORE::exit(0);
>>>>> }
>>>>>
>>>>> print $in->redirect... # For the parent to redirect the browser
>>>>>
>>>>> # Done.
>>>>>
>>>>> Is there a glaring mistake in the above?
>>>>>
>>>>> The parent does no more DB stuff, it just sends a redirect.
>>>>>
>>>>> This runs under ModPerl::Registry.
>>>>>
>>>>> I'd like to get at least one thing working tonight, either the
>>>>> forking or the DBI, I'll be happy!
>>>>>
>>>>> Tosh
>>>>>
>>>>>
>>>>>
>>>>> Perrin Harkins wrote:
>>>>>> On Mon, Jan 25, 2010 at 3:48 PM, Tosh Cooey
>>>>>> <[email protected]> wrote:
>>>>>>> Thanks Perrin, the forking, my child got a PID of 30033 and
>>>>>>> then afterwards
>>>>>>> when I checked the processes (ps) for 30033 I see:
>>>>>>>
>>>>>>> [apache2] <defunct>
>>>>>>>
>>>>>>> Is that what's supposed to happen?
>>>>>> After you call exit? No. It should be gone. That's a zombie
>>>>>> process.
>>>>>>> That PM thread seems to indicate that I must disconnect every
>>>>>>> DBH, not just
>>>>>>> the ones that I will use.
>>>>>> Either that, or you need to set InactiveDestroy on all of them
>>>>>> in the
>>>>>> child process. Otherwise, when the child exits, it messes up
>>>>>> all of
>>>>>> them for the parent.
>>>>>>> Are you also suggesting the use of
>>>>>>> Parallel::ForkManager for forks?
>>>>>> No. The DBI stuff is the same with either.
>>>>>> - Perrin
>>>>>
>>>>> --
>>>>> McIntosh Cooey - Twelve Hundred Group LLC - http://www.
>>>>> 1200group.com/
>>>
>>> --
>>> McIntosh Cooey - Twelve Hundred Group LLC - http://www.
>>> 1200group.com/
>
> --
> McIntosh Cooey - Twelve Hundred Group LLC - http://www.1200group.com/
lmpx.com only provides a reader for public news (NNTP) servers. It is not
affiliated with the servers or forums shown here and is not responsible for
the content of articles, which is written by their respective authors.