You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Marc Slagle <ma...@whapps.com> on 2003/11/10 20:22:18 UTC
[MP1] Apache segfault after serving request
After serving up requests normally for some time, we get the following
line in our error_log:
[Mon Nov 10 13:44:31 2003] [notice] child pid 24121 exit signal
Segmentation fault (11)
There aren't any other entries in the error log for the requests. We
think that this is happening during the normal termination of the child
process (after serving MaxRequestsPerChild requests, or exceeding
GTopLimit limits). The segfaults were happening before we added the
GTopLimit configuration.
Has anybody seen this behavior before? I can send more information if
needed.
Thanks
Useful information:
perl -V reports:
Summary of my perl5 (revision 5.0 version 8 subversion 0) configuration:
Platform:
osname=linux, osvers=2.4.20-8smp, archname=i686-linux
uname='linux ooghij 2.4.20-8smp #1 smp thu mar 13 17:45:54 est 2003
i686 i686 i386 gnulinux '
config_args=''
hint=recommended, useposix=true, d_sigaction=define
usethreads=undef use5005threads=undef useithreads=undef
usemultiplicity=undef
useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
use64bitint=undef use64bitall=undef uselongdouble=undef
usemymalloc=n, bincompat5005=undef
Compiler:
cc='cc', ccflags ='-fno-strict-aliasing -D_LARGEFILE_SOURCE
-D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm',
optimize='-O3',
cppflags='-fno-strict-aliasing -I/usr/include/gdbm'
ccversion='', gccversion='3.2.2 20030222 (Red Hat Linux 3.2.2-5)',
gccosandvers=''
intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t',
lseeksize=8
alignbytes=4, prototype=define
Linker and Libraries:
ld='cc', ldflags =' -L/usr/local/lib'
libpth=/usr/local/lib /lib /usr/lib
libs=-lnsl -lgdbm -ldb -ldl -lm -lc -lcrypt -lutil
perllibs=-lnsl -ldl -lm -lc -lcrypt -lutil
libc=/lib/libc-2.3.2.so, so=so, useshrplib=false, libperl=libperl.a
gnulibc_version='2.3.2'
Dynamic Linking:
dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-rdynamic'
cccdlflags='-fpic', lddlflags='-shared -L/usr/local/lib'
Characteristics of this binary (from libperl):
Compile-time options: USE_LARGE_FILES
Built under linux
Compiled at Jul 31 2003 13:36:56
@INC:
/usr/local/lib/perl5/5.8.0/i686-linux
/usr/local/lib/perl5/5.8.0
/usr/local/lib/perl5/site_perl/5.8.0/i686-linux
/usr/local/lib/perl5/site_perl/5.8.0
/usr/local/lib/perl5/site_perl
.
The version of mod perl we are running is 1.28, with apache 1.28.
We built mod_perl with:
perl Makefile.PL \
APACHE_SRC=../apache_1.3.28/src \
APACHE_PREFIX=/usr/skynet \
DO_HTTPD=1 \
USE_APACI=1 \
EVERYTHING=1 \
APACI_ARGS='--disable-rule=EXPAT --disable-module=env
--disable-module=negotiation --disable-module=status
--disable-module=include --disable-module=autoindex
--disable-module=asis --disable-module=imap --disable-module=actions
--disable-module=userdir --disable-module=setenvif'
The relevant portion of the httpd.conf file:
<VirtualHost 192.168.1.x:80>
ServerAdmin webmaster@whapps.com
DocumentRoot /usr/skynet/htdocs
ServerName skynet.whapps.com
Alias /icons/ "/usr/skynet/htdocs"
PerlTransHandler Skynet::TransHandler
ErrorDocument 401 /authfail.html
<Directory /usr/skynet/htdocs>
AuthName "Password Protected Area"
AuthType Basic
PerlAuthenHandler Skynet::AuthenHandler
require valid-user
PerlSetVar Apache::GTopLimit::DEBUG 1
PerlFixupHandler Apache::GTopLimit
PerlHandler Skynet::Handler
</Directory>
</VirtualHost>
The startup.pl file:
#!/usr/bin/perl
use strict;
use Skynet::Util;
use Apache::GTopLimit;
use Skynet::Handler;
use Apache::DBI;
# Control the life based on memory size
# in KB, so this is ~10MB
$Apache::GTopLimit::MAX_PROCESS_SIZE = 20000;
# Make sure we are in a sane environment.
$ENV{MOD_PERL} or die "not running under mod_perl!";
# Initialize the database connections for each child
#$Apache::DBI::DEBUG = "3";
my
$Dbh=Apache::DBI->connect_on_init("dbi:mysql:dbname=skynet;host=x.com;","user","pass",
{AutoCommit => 1, RaiseError => 1});
1;
A backtrace when the segfault occurs:
GNU gdb Red Hat Linux (5.3post-0.20021129.18rh)
This GDB was configured as "i386-redhat-linux-gnu"...
(gdb) run -X -f /usr/skynet/conf/httpd.conf
Starting program: /usr/skynet/bin/httpd -X -f
/usr/skynet/conf/httpd.conf
Program received signal SIGSEGV, Segmentation fault.
0x0807698b in hvrv2table (rv=0x0) at perl_util.c:101
101 return (table *)SvIV((SV*)SvRV(rv));
(gdb) bt
#0 0x0807698b in hvrv2table (rv=0x0) at perl_util.c:101
#1 0x08088995 in XS_Apache__Table_DESTROY (cv=0x81ae5dc) at Table.c:149
#2 0x0810b6c9 in Perl_pp_entersub ()
#3 0x080ba314 in S_call_body ()
#4 0x080ba0ee in Perl_call_sv ()
#5 0x08112b2b in Perl_sv_clear ()
#6 0x08112d53 in Perl_sv_free ()
#7 0x08117995 in Perl_sv_clean_objs ()
#8 0x080b89f8 in perl_destruct ()
#9 0x0806bd6c in perl_shutdown (s=0x819e12c, p=0x8df749c) at
mod_perl.c:294
#10 0x0806ff43 in perl_child_exit_cleanup (data=0x80000) at
mod_perl.c:926
#11 0x0808a8e4 in run_cleanups (c=0x8df7634) at alloc.c:1745
#12 0x08089183 in ap_clear_pool (a=0x8df749c) at alloc.c:541
#13 0x08089200 in ap_destroy_pool (a=0x8df749c) at alloc.c:571
#14 0x080965ce in clean_child_exit (code=0) at http_main.c:528
#15 0x0809942d in child_main (child_num_arg=0) at http_main.c:4367
#16 0x080999ba in make_child (s=0x819e12c, slot=0, now=1068483979) at
http_main.c:4768
#17 0x08099b20 in startup_children (number_to_start=5) at
http_main.c:4850
#18 0x0809a1bd in standalone_main (argc=4, argv=0xbfffead4) at
http_main.c:5169
#19 0x0809a9db in main (argc=4, argv=0xbfffead4) at http_main.c:5511
#20 0x420156a4 in __libc_start_main () from /lib/tls/libc.so.6
(gdb) list
5511 STANDALONE_MAIN(argc, argv);
5512 }
5513 #else
5514 if (!tpf_child) {
5515 memcpy(tpf_server_name, input_parms.parent.servname,
5516 INETD_SERVNAME_LENGTH);
5517 tpf_server_name[INETD_SERVNAME_LENGTH + 1] = '\0';
5518 sprintf(tpf_mutex_key, "%.*x", TPF_MUTEX_KEY_SIZE - 1,
getpid());
5519 tpf_parent_pid = getppid();
5520 ap_open_logs(server_conf, plog);
(gdb)
Marc Slagle
Whapps, LLC
--
Reporting bugs: http://perl.apache.org/bugs/
Mail list info: http://perl.apache.org/maillist/modperl.html
Re: [MP1] Apache segfault after serving request
Posted by Marc Slagle <ma...@whapps.com>.
> I don't have a test to reproduce the segfault, so I'm just shooting in the
> dark based on the core trace that you've kindly provided. Please revert the
> previous patch and try the new one:
One more bit of information: we were using an older version of
Apache::Request, but upgraded it to the newest version. All parts of
the setup of the server (apache, modules, etc) were all make tested and
passed.
Marc Slagle
Whapps, LLC
--
Reporting bugs: http://perl.apache.org/bugs/
Mail list info: http://perl.apache.org/maillist/modperl.html
Re: [MP1] Apache segfault after serving request
Posted by Marc Slagle <ma...@whapps.com>.
> ALso, Marc, I'd suggest to rethink your coding techniques. Instead of using
> globals you should probably encapsulate all the data that you want to pass
> around into a single object and and pass it around, or using a Singleton
> object. Globals are not the best way to go in majority of cases.
Thanks for all the help. We'll be looking into the Singleton object
today. I agree that globals are not the best way to go. We will
attempt to get our examples as small as possible if we need to post in
the future.
Marc Slagle
Whapps, LLC
--
Reporting bugs: http://perl.apache.org/bugs/
Mail list info: http://perl.apache.org/maillist/modperl.html
Re: [MP1] Apache segfault after serving request
Posted by Stas Bekman <st...@stason.org>.
Joe Schaefer wrote:
> Stas Bekman <st...@stason.org> writes:
>
> [...]
>
>
>>It seems that your global $GlobalS var contains a reference to an
>>Apache::Request table, but A-R object is not global, so when the scope
>>of the handler is exited A-R object gets destroyed, leaving $GlobalS
>>containting a pointer to a black hole. That black hole is req->parms
>>in Request.xs in libapreq.
>
>
> <yack>
> Yup- the request pool's cleanup hook has already come through and
> reclaimed all those C data structures. Unfortunately the perl glue
> isn't aware that this happened.
>
> I think the basic assumption is that the request pool's lifetime must
> be longer than any perl scalar glued to a per-request struct. Of
> course, that assumption doesn't appear to be valid in this situation
> (a global Apache::Table object is alive, but the associated C table was
> freed). Not sure what to do about it right now.
> </yack>
We have exactly the same issue with APR::Pool objects created via
my $parent_pool = APR::Pool->new();
my $child_pool = $parent_pool->new();
if $parent_pool is destroyed first, it also eats the guts of its child,
leaving $child_pool pointing to some invalid thing. The worst thing is that if
some other pool gets allocated at the same pointer where child_pool point, it
will be destroyed!
Moreover, every time you say:
my $parent2 = $child_pool->parent_get;
you can't destroy $parent2, because it will nuke the guts of the parent and
all the children. Therefore you can't just wrap and IV pointer into an SV and
hand it to the perl side.
Currently the solution that almost works is to introduce an internal reference
counting, by incrementing the reference counting every time a new perl
variable pointing to the pool is created, and decrementing when it's attempted
to be destroyed. Only when the reference count reaches 0 we can destroy the
actual pool. This reference counting is stored inside the C pool struct
itself, via user data API.
It's almost working. There is at least one problem with this approach that I
forgot what it was, but I have a test that demonstrates it somewhere. The
solution that I'm thinking to implement involves storing a real SV in the
pool's user data and use Perl's reference counting.
I think the same approach can be taken by A-R. Once I'll polish the solution
with APR::Pool, we can apply it to A-R. In any case I've provided Marc with a
workaround which should prevent segfaults, so there is no rush to fix it if
you are busy with more urgent things.
ALso, Marc, I'd suggest to rethink your coding techniques. Instead of using
globals you should probably encapsulate all the data that you want to pass
around into a single object and and pass it around, or using a Singleton
object. Globals are not the best way to go in majority of cases.
__________________________________________________________________
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: [MP1] Apache segfault after serving request
Posted by Stas Bekman <st...@stason.org>.
Joe Schaefer wrote:
> Stas Bekman <st...@stason.org> writes:
>
> [...]
>
>
>>It seems that your global $GlobalS var contains a reference to an
>>Apache::Request table, but A-R object is not global, so when the scope
>>of the handler is exited A-R object gets destroyed, leaving $GlobalS
>>containting a pointer to a black hole. That black hole is req->parms
>>in Request.xs in libapreq.
>
>
> <yack>
> Yup- the request pool's cleanup hook has already come through and
> reclaimed all those C data structures. Unfortunately the perl glue
> isn't aware that this happened.
>
> I think the basic assumption is that the request pool's lifetime must
> be longer than any perl scalar glued to a per-request struct. Of
> course, that assumption doesn't appear to be valid in this situation
> (a global Apache::Table object is alive, but the associated C table was
> freed). Not sure what to do about it right now.
> </yack>
We have exactly the same issue with APR::Pool objects created via
my $parent_pool = APR::Pool->new();
my $child_pool = $parent_pool->new();
if $parent_pool is destroyed first, it also eats the guts of its child,
leaving $child_pool pointing to some invalid thing. The worst thing is that if
some other pool gets allocated at the same pointer where child_pool point, it
will be destroyed!
Moreover, every time you say:
my $parent2 = $child_pool->parent_get;
you can't destroy $parent2, because it will nuke the guts of the parent and
all the children. Therefore you can't just wrap and IV pointer into an SV and
hand it to the perl side.
Currently the solution that almost works is to introduce an internal reference
counting, by incrementing the reference counting every time a new perl
variable pointing to the pool is created, and decrementing when it's attempted
to be destroyed. Only when the reference count reaches 0 we can destroy the
actual pool. This reference counting is stored inside the C pool struct
itself, via user data API.
It's almost working. There is at least one problem with this approach that I
forgot what it was, but I have a test that demonstrates it somewhere. The
solution that I'm thinking to implement involves storing a real SV in the
pool's user data and use Perl's reference counting.
I think the same approach can be taken by A-R. Once I'll polish the solution
with APR::Pool, we can apply it to A-R. In any case I've provided Marc with a
workaround which should prevent segfaults, so there is no rush to fix it if
you are busy with more urgent things.
ALso, Marc, I'd suggest to rethink your coding techniques. Instead of using
globals you should probably encapsulate all the data that you want to pass
around into a single object and and pass it around, or using a Singleton
object. Globals are not the best way to go in majority of cases.
__________________________________________________________________
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
Re: [MP1] Apache segfault after serving request
Posted by Joe Schaefer <jo...@sunstarsys.com>.
Stas Bekman <st...@stason.org> writes:
[...]
> It seems that your global $GlobalS var contains a reference to an
> Apache::Request table, but A-R object is not global, so when the scope
> of the handler is exited A-R object gets destroyed, leaving $GlobalS
> containting a pointer to a black hole. That black hole is req->parms
> in Request.xs in libapreq.
<yack>
Yup- the request pool's cleanup hook has already come through and
reclaimed all those C data structures. Unfortunately the perl glue
isn't aware that this happened.
I think the basic assumption is that the request pool's lifetime must
be longer than any perl scalar glued to a per-request struct. Of
course, that assumption doesn't appear to be valid in this situation
(a global Apache::Table object is alive, but the associated C table was
freed). Not sure what to do about it right now.
</yack>
[...]
> Joe, any ideas on this one? (we are talking about libapreq1/mp1) May
> be we should just assume that it's OK that the A-R table was already
> freed? Does this patch introduce a leak?
I don't know- I'll try to think about it more carefully before the week
is over.
Thanks, Stas.
--
Joe Schaefer
Re: [MP1] Apache segfault after serving request
Posted by Stas Bekman <st...@stason.org>.
Further reduced to the minimal:
<Location /crash2>
SetHandler perl-script
PerlHandler Server::Killer
</Location>
package Server::Killer;
use 5.008;
use strict;
use Apache::Request;
use Apache::Constants qw(:common);
our $GlobalS;
sub handler
{
my $r = shift;
$r->send_http_header;
$r->print("ok");
my $q=Apache::Request->new($r);
$GlobalS=$q->param();
return OK;
}
1;
This patch against the current cvs prevents the segfault. Though it doesn't
eliminate the problem, since it's caused elsewhere.
Index: src/modules/perl/perl_util.c
===================================================================
RCS file: /home/cvs/modperl/src/modules/perl/perl_util.c,v
retrieving revision 1.53
diff -u -r1.53 perl_util.c
--- src/modules/perl/perl_util.c 30 Oct 2003 19:39:17 -0000 1.53
+++ src/modules/perl/perl_util.c 13 Nov 2003 01:33:46 -0000
@@ -96,6 +96,7 @@
if(SvROK(rv) && SvTYPE(SvRV(rv)) == SVt_PVHV) {
SV *sv = perl_hvrv_magic_obj(rv);
if(!sv) croak("HV is not magic!");
+ if(!SvROK(sv)) croak("trying to free magic that was freed already!");
return (table *)SvIV((SV*)SvRV(sv));
}
return (table *)SvIV((SV*)SvRV(rv));
It seems that your global $GlobalS var contains a reference to an
Apache::Request table, but A-R object is not global, so when the scope of the
handler is exited A-R object gets destroyed, leaving $GlobalS containting a
pointer to a black hole. That black hole is req->parms in Request.xs in libapreq.
And here is a quick workaround for you, while we are figuring out the origin
problem:
$r->push_handlers(PerlCleanupHandler =>
sub { undef $GlobalS if defined $GlobalS } );
So the new handler now looks like:
package Server::Killer;
use 5.008;
use strict;
use Apache::Request;
use Apache::Constants qw(:common);
our $GlobalS;
sub handler
{
my $r = shift;
$r->send_http_header;
$r->print("ok");
my $q=Apache::Request->new($r);
$GlobalS=$q->param();
$r->push_handlers(PerlCleanupHandler =>
sub { undef $GlobalS if defined $GlobalS } );
return OK;
}
1;
Actually a simple:
undef $GlobalS;
return OK;
}
does the trick. Again, what you want to achieve is destroying that global
reference to parm before A-R object is destroyed.
Though, since in your original code you import the global symbols you will
need to destroy them in the package they were created. But this will do the trick:
$GlobalS = undef;
return OK;
}
as it'll affect the alias as well as the exported variable, putting the
reference counting to 0.
Joe, any ideas on this one? (we are talking about libapreq1/mp1) May be we
should just assume that it's OK that the A-R table was already freed? Does
this patch introduce a leak? I'd suggest to write a test for libapreq2 to
cover this case.
Index: src/modules/perl/perl_util.c
===================================================================
RCS file: /home/cvs/modperl/src/modules/perl/perl_util.c,v
retrieving revision 1.53
diff -u -r1.53 perl_util.c
--- src/modules/perl/perl_util.c 30 Oct 2003 19:39:17 -0000 1.53
+++ src/modules/perl/perl_util.c 13 Nov 2003 01:49:48 -0000
@@ -96,6 +96,8 @@
if(SvROK(rv) && SvTYPE(SvRV(rv)) == SVt_PVHV) {
SV *sv = perl_hvrv_magic_obj(rv);
if(!sv) croak("HV is not magic!");
+ /* already freed? */
+ if(!SvROK(sv)) return (table *)NULL;
return (table *)SvIV((SV*)SvRV(sv));
}
return (table *)SvIV((SV*)SvRV(rv));
Index: src/modules/perl/Table.xs
===================================================================
RCS file: /home/cvs/modperl/src/modules/perl/Table.xs,v
retrieving revision 1.10
diff -u -r1.10 Table.xs
--- src/modules/perl/Table.xs 23 May 2000 15:56:12 -0000 1.10
+++ src/modules/perl/Table.xs 13 Nov 2003 01:49:48 -0000
@@ -114,9 +114,13 @@
Apache__Table tab;
CODE:
- tab = (Apache__Table)hvrv2table(self);
- if(SvROK(self) && SvTYPE(SvRV(self)) == SVt_PVHV)
- safefree(tab);
+ if(self && SvROK(self) && SvTYPE(SvRV(self)) == SVt_PVHV) {
+ tab = (Apache__Table)hvrv2table(self);
+ if (tab) {
+ safefree(tab);
+
+ }
+ }
void
FETCH(self, key)
__________________________________________________________________
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: [MP1] Apache segfault after serving request
Posted by Stas Bekman <st...@stason.org>.
Further reduced to the minimal:
<Location /crash2>
SetHandler perl-script
PerlHandler Server::Killer
</Location>
package Server::Killer;
use 5.008;
use strict;
use Apache::Request;
use Apache::Constants qw(:common);
our $GlobalS;
sub handler
{
my $r = shift;
$r->send_http_header;
$r->print("ok");
my $q=Apache::Request->new($r);
$GlobalS=$q->param();
return OK;
}
1;
This patch against the current cvs prevents the segfault. Though it doesn't
eliminate the problem, since it's caused elsewhere.
Index: src/modules/perl/perl_util.c
===================================================================
RCS file: /home/cvs/modperl/src/modules/perl/perl_util.c,v
retrieving revision 1.53
diff -u -r1.53 perl_util.c
--- src/modules/perl/perl_util.c 30 Oct 2003 19:39:17 -0000 1.53
+++ src/modules/perl/perl_util.c 13 Nov 2003 01:33:46 -0000
@@ -96,6 +96,7 @@
if(SvROK(rv) && SvTYPE(SvRV(rv)) == SVt_PVHV) {
SV *sv = perl_hvrv_magic_obj(rv);
if(!sv) croak("HV is not magic!");
+ if(!SvROK(sv)) croak("trying to free magic that was freed already!");
return (table *)SvIV((SV*)SvRV(sv));
}
return (table *)SvIV((SV*)SvRV(rv));
It seems that your global $GlobalS var contains a reference to an
Apache::Request table, but A-R object is not global, so when the scope of the
handler is exited A-R object gets destroyed, leaving $GlobalS containting a
pointer to a black hole. That black hole is req->parms in Request.xs in libapreq.
And here is a quick workaround for you, while we are figuring out the origin
problem:
$r->push_handlers(PerlCleanupHandler =>
sub { undef $GlobalS if defined $GlobalS } );
So the new handler now looks like:
package Server::Killer;
use 5.008;
use strict;
use Apache::Request;
use Apache::Constants qw(:common);
our $GlobalS;
sub handler
{
my $r = shift;
$r->send_http_header;
$r->print("ok");
my $q=Apache::Request->new($r);
$GlobalS=$q->param();
$r->push_handlers(PerlCleanupHandler =>
sub { undef $GlobalS if defined $GlobalS } );
return OK;
}
1;
Actually a simple:
undef $GlobalS;
return OK;
}
does the trick. Again, what you want to achieve is destroying that global
reference to parm before A-R object is destroyed.
Though, since in your original code you import the global symbols you will
need to destroy them in the package they were created. But this will do the trick:
$GlobalS = undef;
return OK;
}
as it'll affect the alias as well as the exported variable, putting the
reference counting to 0.
Joe, any ideas on this one? (we are talking about libapreq1/mp1) May be we
should just assume that it's OK that the A-R table was already freed? Does
this patch introduce a leak? I'd suggest to write a test for libapreq2 to
cover this case.
Index: src/modules/perl/perl_util.c
===================================================================
RCS file: /home/cvs/modperl/src/modules/perl/perl_util.c,v
retrieving revision 1.53
diff -u -r1.53 perl_util.c
--- src/modules/perl/perl_util.c 30 Oct 2003 19:39:17 -0000 1.53
+++ src/modules/perl/perl_util.c 13 Nov 2003 01:49:48 -0000
@@ -96,6 +96,8 @@
if(SvROK(rv) && SvTYPE(SvRV(rv)) == SVt_PVHV) {
SV *sv = perl_hvrv_magic_obj(rv);
if(!sv) croak("HV is not magic!");
+ /* already freed? */
+ if(!SvROK(sv)) return (table *)NULL;
return (table *)SvIV((SV*)SvRV(sv));
}
return (table *)SvIV((SV*)SvRV(rv));
Index: src/modules/perl/Table.xs
===================================================================
RCS file: /home/cvs/modperl/src/modules/perl/Table.xs,v
retrieving revision 1.10
diff -u -r1.10 Table.xs
--- src/modules/perl/Table.xs 23 May 2000 15:56:12 -0000 1.10
+++ src/modules/perl/Table.xs 13 Nov 2003 01:49:48 -0000
@@ -114,9 +114,13 @@
Apache__Table tab;
CODE:
- tab = (Apache__Table)hvrv2table(self);
- if(SvROK(self) && SvTYPE(SvRV(self)) == SVt_PVHV)
- safefree(tab);
+ if(self && SvROK(self) && SvTYPE(SvRV(self)) == SVt_PVHV) {
+ tab = (Apache__Table)hvrv2table(self);
+ if (tab) {
+ safefree(tab);
+
+ }
+ }
void
FETCH(self, key)
__________________________________________________________________
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
Re: [MP1] Apache segfault after serving request
Posted by Stas Bekman <st...@stason.org>.
Marc Slagle wrote:
>>I don't have a test to reproduce the segfault, so I'm just shooting in the
>>dark based on the core trace that you've kindly provided. Please revert the
>>previous patch and try the new one:
>
>
> We tried the new patch, but can still get the segfault. We wrote 3
> modules that can reproduce the segfault on our system.
Here is a simple test that I was after. No XML, no XSLT, no extra modules
needed (i.e. no wasted time on developer's behalf). In the future please try
to come up with a similar test if possible.
package Server::Killer;
use 5.008;
use strict;
use Apache::Request;
use Apache::Constants qw(:common);
our $GlobalURI;
our $GlobalS;
sub handler
{
my $r=Apache::Request->new(shift);
$r->send_http_header;
$r->print("ok");
my $S=$r->param();
$GlobalS=$r->param();
my $Stuff=&readglobal;
return OK;
}
sub readglobal
{
my $Uri=$GlobalURI;
return $Uri;
}
1;
Same goes for the required config section, please always provide a minimal
config if possible. Here all was needed is:
Listen 127.0.0.1:8123
NameVirtualHost 127.0.0.1:8123
<VirtualHost 127.0.0.1:8123>
PerlTransHandler Server::KillerTH
<Directory /home/httpd/httpd_perl/docs>
PerlHandler Server::Killer
</Directory>
</VirtualHost>
Now it's easy to reproduce the segfault. Set MaxRequestPerChild 1 and run the
server with 'httpd -X', it crashes after the first request.
It crashes when it tries to destroy $GlobalS (during child_exit), which
contains a reference to an Apache::Table object which was already freed. Some
reference counting is going wrong. I'm still looking at 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: [MP1] Apache segfault after serving request
Posted by Stas Bekman <st...@stason.org>.
Stas Bekman wrote:
> Marc Slagle wrote:
> [...]
>
>> If you need any more information, please let us know.
>
>
> I went through the pain of installing all these prerequisited just to
> run your handlers, but it works just fine for me. I've tried to match
> the perl-5.8.0 build and the only difference I think is that I used the
> latest modperl from cvs. Also all the latest xml/xslt libs. Let me know
> if you want me to provide you some info about the used components.
Actually, no, I do get the segfault, which is good. I forgot that I need to
run it several times. More on this later...
__________________________________________________________________
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: [MP1] Apache segfault after serving request
Posted by Stas Bekman <st...@stason.org>.
Marc Slagle wrote:
[...]
> If you need any more information, please let us know.
I went through the pain of installing all these prerequisited just to run your
handlers, but it works just fine for me. I've tried to match the perl-5.8.0
build and the only difference I think is that I used the latest modperl from
cvs. Also all the latest xml/xslt libs. Let me know if you want me to provide
you some info about the used components.
__________________________________________________________________
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: [MP1] Apache segfault after serving request
Posted by Marc Slagle <ma...@whapps.com>.
> I don't have a test to reproduce the segfault, so I'm just shooting in the
> dark based on the core trace that you've kindly provided. Please revert the
> previous patch and try the new one:
We tried the new patch, but can still get the segfault. We wrote 3
modules that can reproduce the segfault on our system. We're using the
same trickery in our production code. The segfault will occur when the
server is under a bit of load, refreshing the browser repeatedly will
make it die quickly. We have apache configured so the children only
handle 10 requests before exiting.
The transhandler will answer requests for any domain name, and strip the
uri passed off of the request. It returns declined after that so our
handler can step in and do its work.
The handler is parsing an XML file and using XML::GDOME::XSLT to
transform it into html. We used XML::LibXSLT for a while too, the
segfaults were happening before we switched over.
The Global Module is just a locker for storing the parts of the request
we want to access from modules down the line.
Some code we didn't include calls different objects based on the uri
passed in. But we could reproduce the bomb without all of that.
We compiled apache without expat, having read that this can cause
segfaults when using some XML modules.
The latest backtrace and the portion of httpd.conf that sets up the test
environment are in the README for Server::Killer. We don't want to take
too much of your time with this, if we knew what portion of our code was
causing the bomb then we could just recode it.
If you need any more information, please let us know.
Thanks again,
Marc Slagle
Whapps, LLC
Re: [MP1] Apache segfault after serving request
Posted by Stas Bekman <st...@stason.org>.
Marc Slagle wrote:
[...]
> Thanks for the reply. Unfortunately the patch didn't resolve the
> problem. The backtrace does look somewhat different, its making some
> new calls before the segfault that it wasn't before. Numbers 4-13 show
> differently:
[...]
I don't have a test to reproduce the segfault, so I'm just shooting in the
dark based on the core trace that you've kindly provided. Please revert the
previous patch and try the new one:
Index: src/modules/perl/Table.xs
===================================================================
RCS file: /home/cvs/modperl/src/modules/perl/Table.xs,v
retrieving revision 1.10
diff -u -r1.10 Table.xs
--- src/modules/perl/Table.xs 23 May 2000 15:56:12 -0000 1.10
+++ src/modules/perl/Table.xs 10 Nov 2003 22:33:09 -0000
@@ -114,9 +114,10 @@
Apache__Table tab;
CODE:
- tab = (Apache__Table)hvrv2table(self);
- if(SvROK(self) && SvTYPE(SvRV(self)) == SVt_PVHV)
+ if(self && SvROK(self) && SvTYPE(SvRV(self)) == SVt_PVHV) {
+ tab = (Apache__Table)hvrv2table(self);
safefree(tab);
+ }
void
FETCH(self, key)
I wonder why SvROK(NULL) returns true. It doesn't make any sense.
__________________________________________________________________
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: [MP1] Apache segfault after serving request
Posted by Marc Slagle <ma...@whapps.com>.
> Please try this patch:
>
> Index: src/modules/perl/Table.xs
> ===================================================================
> RCS file: /home/cvs/modperl/src/modules/perl/Table.xs,v
> retrieving revision 1.10
> diff -u -r1.10 Table.xs
> --- src/modules/perl/Table.xs 23 May 2000 15:56:12 -0000 1.10
> +++ src/modules/perl/Table.xs 10 Nov 2003 19:46:55 -0000
> @@ -114,9 +114,10 @@
> Apache__Table tab;
>
> CODE:
> - tab = (Apache__Table)hvrv2table(self);
> - if(SvROK(self) && SvTYPE(SvRV(self)) == SVt_PVHV)
> + if(SvROK(self) && SvTYPE(SvRV(self)) == SVt_PVHV) {
> + tab = (Apache__Table)hvrv2table(self);
> safefree(tab);
> + }
>
> void
> FETCH(self, key)
Thanks for the reply. Unfortunately the patch didn't resolve the
problem. The backtrace does look somewhat different, its making some
new calls before the segfault that it wasn't before. Numbers 4-13 show
differently:
GNU gdb Red Hat Linux (5.3post-0.20021129.18rh)
This GDB was configured as "i386-redhat-linux-gnu"...
(gdb) run -X -f /usr/skynet/conf/httpd.conf
Starting program: /usr/skynet/bin/httpd -X -f
/usr/skynet/conf/httpd.conf
Program received signal SIGSEGV, Segmentation fault.
0x0807698b in hvrv2table (rv=0x0) at perl_util.c:101
101 return (table *)SvIV((SV*)SvRV(rv));
(gdb) bt
#0 0x0807698b in hvrv2table (rv=0x0) at perl_util.c:101
#1 0x080889b6 in XS_Apache__Table_DESTROY (cv=0x81ad57c) at Table.c:150
#2 0x0810b6c5 in Perl_pp_entersub ()
#3 0x080ba310 in S_call_body ()
#4 0x080ba0ea in Perl_call_sv ()
#5 0x08112b27 in Perl_sv_clear ()
#6 0x08112d4f in Perl_sv_free ()
#7 0x081126af in Perl_sv_clear ()
#8 0x08112d4f in Perl_sv_free ()
#9 0x081031b1 in Perl_hv_free_ent ()
#10 0x081032f2 in S_hfreeentries ()
#11 0x08103c93 in Perl_hv_undef ()
#12 0x08112961 in Perl_sv_clear ()
#13 0x08112d4f in Perl_sv_free ()
#14 0x08117991 in Perl_sv_clean_objs ()
#15 0x080b89f4 in perl_destruct ()
#16 0x0806bd6c in perl_shutdown (s=0x819d0cc, p=0x8deca64) at
mod_perl.c:294
#17 0x0806ff43 in perl_child_exit_cleanup (data=0x80000) at
mod_perl.c:926
#18 0x0808a8e0 in run_cleanups (c=0x8decbfc) at alloc.c:1745
#19 0x0808917f in ap_clear_pool (a=0x8deca64) at alloc.c:541
#20 0x080891fc in ap_destroy_pool (a=0x8deca64) at alloc.c:571
#21 0x080965ca in clean_child_exit (code=0) at http_main.c:528
#22 0x08099429 in child_main (child_num_arg=0) at http_main.c:4367
#23 0x080999b6 in make_child (s=0x819d0cc, slot=0, now=1068497097) at
http_main.c:4768
#24 0x08099b1c in startup_children (number_to_start=5) at
http_main.c:4850
#25 0x0809a1b9 in standalone_main (argc=4, argv=0xbfffe2c4) at
http_main.c:5169
#26 0x0809a9d7 in main (argc=4, argv=0xbfffe2c4) at http_main.c:5511
#27 0x420156a4 in __libc_start_main () from /lib/tls/libc.so.6
(gdb) list
5511 STANDALONE_MAIN(argc, argv);
5512 }
5513 #else
5514 if (!tpf_child) {
5515 memcpy(tpf_server_name, input_parms.parent.servname,
5516 INETD_SERVNAME_LENGTH);
5517 tpf_server_name[INETD_SERVNAME_LENGTH + 1] = '\0';
5518 sprintf(tpf_mutex_key, "%.*x", TPF_MUTEX_KEY_SIZE - 1,
getpid());
5519 tpf_parent_pid = getppid();
5520 ap_open_logs(server_conf, plog);
We rebuilt the server using new clean tarballs of apache and mod_perl.
Thanks again for your help.
Marc Slagle
Whapps, LLC
--
Reporting bugs: http://perl.apache.org/bugs/
Mail list info: http://perl.apache.org/maillist/modperl.html
Re: [MP1] Apache segfault after serving request
Posted by Stas Bekman <st...@stason.org>.
Marc Slagle wrote:
> After serving up requests normally for some time, we get the following
> line in our error_log:
>
> [Mon Nov 10 13:44:31 2003] [notice] child pid 24121 exit signal
> Segmentation fault (11)
>
> There aren't any other entries in the error log for the requests. We
> think that this is happening during the normal termination of the child
> process (after serving MaxRequestsPerChild requests, or exceeding
> GTopLimit limits). The segfaults were happening before we added the
> GTopLimit configuration.
[...]
> A backtrace when the segfault occurs:
> GNU gdb Red Hat Linux (5.3post-0.20021129.18rh)
> This GDB was configured as "i386-redhat-linux-gnu"...
> (gdb) run -X -f /usr/skynet/conf/httpd.conf
> Starting program: /usr/skynet/bin/httpd -X -f
> /usr/skynet/conf/httpd.conf
>
> Program received signal SIGSEGV, Segmentation fault.
> 0x0807698b in hvrv2table (rv=0x0) at perl_util.c:101
> 101 return (table *)SvIV((SV*)SvRV(rv));
> (gdb) bt
> #0 0x0807698b in hvrv2table (rv=0x0) at perl_util.c:101
> #1 0x08088995 in XS_Apache__Table_DESTROY (cv=0x81ae5dc) at Table.c:149
Thanks for the detailed report, Marc
Please try this patch:
Index: src/modules/perl/Table.xs
===================================================================
RCS file: /home/cvs/modperl/src/modules/perl/Table.xs,v
retrieving revision 1.10
diff -u -r1.10 Table.xs
--- src/modules/perl/Table.xs 23 May 2000 15:56:12 -0000 1.10
+++ src/modules/perl/Table.xs 10 Nov 2003 19:46:55 -0000
@@ -114,9 +114,10 @@
Apache__Table tab;
CODE:
- tab = (Apache__Table)hvrv2table(self);
- if(SvROK(self) && SvTYPE(SvRV(self)) == SVt_PVHV)
+ if(SvROK(self) && SvTYPE(SvRV(self)) == SVt_PVHV) {
+ tab = (Apache__Table)hvrv2table(self);
safefree(tab);
+ }
void
FETCH(self, key)
__________________________________________________________________
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