You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Alexander Bergolth <le...@strike.wu-wien.ac.at> on 2004/01/08 16:58:54 UTC

mod_perl2 (ModPerl::Registry) crashes httpd if request-object is used in a subroutine

Hi!

I'm suffering from the following problem:
When I'm using the request-object in a subroutine without having passed
it to the sub as a parameter, the apache child processes die with a 
segmentation fault when being reused. If httpd is started with prefork 
and StartServers 8, the first 8 requests work but the 9th request kills 
all 8 httpd child processes. (They are being restarted by the main http 
process after that.) If httpd is started as "httpd -X" (single process), 
the first request works and the second crashes the server.

An example script that I've be used to reproce the error on two machines 
running Fedora Core 1 is added below.

I've tried
   httpd-2.0.47-10
   mod_perl-1.99_09-10
   perl-5.8.1-92
   apr-0.9.4-2
and
   httpd-2.0.48-4
   mod_perl-1.99_11-3
   perl-5.8.2-7
   apr-0.9.4-2
   (from Fedora Development)

Unfortunately I couldn't get a useful stacktrace with those binary (and 
-debuginfo) rpms.

---------- snipp! ----------
#!/usr/bin/perl

use strict;

my $r = shift;
$r->content_type("text/html");
$r->print( "<html>\n"
           ."<head><title>Testpage</title></head>\n"
           ."<body>\n" );

&printline1($r, "This works");
&printline2("This crashes the httpd process when it is reused");

$r->print( "</body>\n"
           ."</html>\n" );

sub printline1 {
   my $r = shift;
   $r->print($_[0]."<br>\n");
}

sub printline2 {
   $r->print($_[0]."<br>\n");
}

1;
---------- snipp! ----------

Any hints?

Cheers,
--leo
-- 
-----------------------------------------------------------------------
Alexander (Leo) Bergolth                          leo@leo.wu-wien.ac.at
WU-Wien - Zentrum fuer Informatikdienste       http://leo.wu-wien.ac.at
                  Computers are like air conditioners -
            they stop working properly when you open Windows


-- 
Reporting bugs: http://perl.apache.org/bugs/
Mail list info: http://perl.apache.org/maillist/modperl.html


Re: mod_perl2 (ModPerl::Registry) crashes httpd if request-object is used in a subroutine

Posted by Stas Bekman <st...@stason.org>.
Perrin Harkins wrote:
> On Thu, 2004-01-08 at 16:34, Stas Bekman wrote:
> 
>>But since we expect most modules to run under any MPM, it usually applies to 
>>any code.
> 
> 
> Any code that you plan to release on CPAN, that is.  It's still okay in
> internal code when you know you won't be running threaded MPMs.

You are correct, Perrin.

__________________________________________________________________
Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/     mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com


-- 
Reporting bugs: http://perl.apache.org/bugs/
Mail list info: http://perl.apache.org/maillist/modperl.html


Re: mod_perl2 (ModPerl::Registry) crashes httpd if request-object is used in a subroutine

Posted by Perrin Harkins <pe...@elem.com>.
On Thu, 2004-01-08 at 16:34, Stas Bekman wrote:
> But since we expect most modules to run under any MPM, it usually applies to 
> any code.

Any code that you plan to release on CPAN, that is.  It's still okay in
internal code when you know you won't be running threaded MPMs.

- Perrin


-- 
Reporting bugs: http://perl.apache.org/bugs/
Mail list info: http://perl.apache.org/maillist/modperl.html


Re: mod_perl2 (ModPerl::Registry) crashes httpd if request-object is used in a subroutine

Posted by Stas Bekman <st...@stason.org>.
Perrin Harkins wrote:
[...]
>>Moreover I've read that Apache->request should be avoided in mod_perl2:
>>http://perl.apache.org/docs/2.0/user/porting/compat.html#C_Apache_E_gt_request_
> 
> 
> That only applies to threaded MPMs, and modules you release that others
> might want to run under threaded MPMs.

But since we expect most modules to run under any MPM, it usually applies to 
any code.

I doubt one ever needs to use Apache->request. CGI.pm now accepts $r as an 
argument to CGI->new() and if you need to access $r from elsewhere in your 
code a Singleton should be used.

__________________________________________________________________
Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/     mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com


-- 
Reporting bugs: http://perl.apache.org/bugs/
Mail list info: http://perl.apache.org/maillist/modperl.html


Re: mod_perl2 (ModPerl::Registry) crashes httpd if request-object is used in a subroutine

Posted by Alexander Bergolth <le...@strike.wu-wien.ac.at>.
On 01/08/2004 10:14 PM, Perrin Harkins wrote:
> On Thu, 2004-01-08 at 15:43, Alexander Bergolth wrote:
> 
>>Why do I create a closure? If i'd create a closure I would have to store 
>>a reference to an _anonymous sub
> 
> No, that's a common misconception.  Closures and anonymous subs are two
> totally separate things, although they can be used together.  See the
> explanation here:
> http://perl.apache.org/docs/general/perl_reference/perl_reference.html#Understanding_Closures____the_Easy_Way

Thanks for the explanation!

--leo
-- 
-----------------------------------------------------------------------
Alexander (Leo) Bergolth                          leo@leo.wu-wien.ac.at
WU-Wien - Zentrum fuer Informatikdienste       http://leo.wu-wien.ac.at
                  Computers are like air conditioners -
            they stop working properly when you open Windows


-- 
Reporting bugs: http://perl.apache.org/bugs/
Mail list info: http://perl.apache.org/maillist/modperl.html


Re: mod_perl2 (ModPerl::Registry) crashes httpd if request-object is used in a subroutine

Posted by Perrin Harkins <pe...@elem.com>.
On Thu, 2004-01-08 at 15:43, Alexander Bergolth wrote:
> Why do I create a closure? If i'd create a closure I would have to store 
> a reference to an _anonymous sub

No, that's a common misconception.  Closures and anonymous subs are two
totally separate things, although they can be used together.  See the
explanation here:
http://perl.apache.org/docs/general/perl_reference/perl_reference.html#Understanding_Closures____the_Easy_Way

There is more discussion in the list archives.

> My version uses a regular (named-) sub and the scope of the variable $r 
> should be lexically local to the enclosing block.

And it is, but your sub creates a closure so that when $r changes in the
enclosing block that is not seen in your sub.  The simplest solution is
to pass $r every time.

> Moreover I've read that Apache->request should be avoided in mod_perl2:
> http://perl.apache.org/docs/2.0/user/porting/compat.html#C_Apache_E_gt_request_

That only applies to threaded MPMs, and modules you release that others
might want to run under threaded MPMs.

- Perrin


-- 
Reporting bugs: http://perl.apache.org/bugs/
Mail list info: http://perl.apache.org/maillist/modperl.html


Re: mod_perl2 (ModPerl::Registry) crashes httpd if request-object is used in a subroutine

Posted by Alexander Bergolth <le...@strike.wu-wien.ac.at>.
On 01/08/04 19:15, Perrin Harkins wrote:
> Alexander Bergolth wrote:
> 
>> When I'm using the request-object in a subroutine without having passed
>> it to the sub as a parameter, the apache child processes die with a 
>> segmentation fault when being reused.
> 
> Well, it probably shouldn't segfault, but you can't do that.  You are 
> creating a closure which will permanently keep a copy of the very first 
> $r that existed in that process, but $r is really an apache structure 
> that gets freed after each request.  If you need a copy of $r but don't 
> want to pass it, and you are running in pre-fork MPM, you can use the 
> Apache->request() call.

Why do I create a closure? If i'd create a closure I would have to store 
a reference to an _anonymous sub, something like that:

---------- snipp! ----------
my $r = shift;

my $printline3 = sub {
   $r->print($_[0]."<br>\n");
}

&$printline3("Uses frozen request variable.");
---------- snipp! ----------
( See http://www.perldoc.com/perl5.6/pod/perlref.html#4. )

My version uses a regular (named-) sub and the scope of the variable $r 
should be lexically local to the enclosing block. So the value of $r 
should be the same as in the "main" block, where it is assigned via
"$r = shift;" at every new request. (I've again attached my version 
below for the sake of completeness.)

Moreover I've read that Apache->request should be avoided in mod_perl2:
http://perl.apache.org/docs/2.0/user/porting/compat.html#C_Apache_E_gt_request_

---------- snipp! ----------
#!/usr/bin/perl

use strict;

my $r = shift;
$r->content_type("text/html");
$r->print( "<html>\n"
           ."<head><title>Testpage</title></head>\n"
           ."<body>\n" );

&printline1($r, "This works");
&printline2("This crashes the httpd process when it is reused");

$r->print( "</body>\n"
           ."</html>\n" );

sub printline1 {
   my $r = shift;
   $r->print($_[0]."<br>\n");
}

sub printline2 {
   $r->print($_[0]."<br>\n");
}

1;
---------- snipp! ----------

Cheers,
--leo
-- 
-----------------------------------------------------------------------
Alexander (Leo) Bergolth                          leo@leo.wu-wien.ac.at
WU-Wien - Zentrum fuer Informatikdienste       http://leo.wu-wien.ac.at
                  Computers are like air conditioners -
            they stop working properly when you open Windows


-- 
Reporting bugs: http://perl.apache.org/bugs/
Mail list info: http://perl.apache.org/maillist/modperl.html


Re: mod_perl2 (ModPerl::Registry) crashes httpd if request-object is used in a subroutine

Posted by Stas Bekman <st...@stason.org>.
Perrin Harkins wrote:
> Alexander Bergolth wrote:
> 
>> When I'm using the request-object in a subroutine without having passed
>> it to the sub as a parameter, the apache child processes die with a 
>> segmentation fault when being reused.
> 
> 
> Well, it probably shouldn't segfault, but you can't do that.  You are 
> creating a closure which will permanently keep a copy of the very first 
> $r that existed in that process, but $r is really an apache structure 
> that gets freed after each request.  If you need a copy of $r but don't 
> want to pass it, and you are running in pre-fork MPM, you can use the 
> Apache->request() call.

I've looked at trying to avoid the segfault. I think we can't much do about 
it. Any object with C guts can be trapped in the closure and contain a pointer 
to invalid data on subsequent accesses. You can't check whether the pointer to 
the C object is invalid or not. Since its members all look valid and the 
memory it used to occupy has been freed already, it may or may not be 
overtaken by someone else, so there is no reliable test.

Let's say we have added some signature to each object that marks it as 
destroyed on DESTROY. Then we could check that validity flag in every method 
attempting to use that object. But it'll add CPU and memory overhead which 
normally is not needed, since the closure created by Alexander is a bug in his 
program and not a normal behavior.

I'm quite sure that you will have the same problem with mp1, if you run that 
closure script on it.

__________________________________________________________________
Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/     mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com


-- 
Reporting bugs: http://perl.apache.org/bugs/
Mail list info: http://perl.apache.org/maillist/modperl.html


Re: mod_perl2 (ModPerl::Registry) crashes httpd if request-object is used in a subroutine

Posted by Perrin Harkins <pe...@elem.com>.
Alexander Bergolth wrote:
> When I'm using the request-object in a subroutine without having passed
> it to the sub as a parameter, the apache child processes die with a 
> segmentation fault when being reused.

Well, it probably shouldn't segfault, but you can't do that.  You are 
creating a closure which will permanently keep a copy of the very first 
$r that existed in that process, but $r is really an apache structure 
that gets freed after each request.  If you need a copy of $r but don't 
want to pass it, and you are running in pre-fork MPM, you can use the 
Apache->request() call.

- Perrin


-- 
Reporting bugs: http://perl.apache.org/bugs/
Mail list info: http://perl.apache.org/maillist/modperl.html