You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Ed...@priorityhealth.com on 2006/11/15 22:47:56 UTC

[MP2] Seg Fault in Registry script "print" using output filter handler

I'm getting seg faults within "print" of ModPerl::Registry script while
using an output filter handler. The output filter is run during the
script's "print" statement when the printed string is > ~8kb. Debugging
shows the seg fault occurs AFTER the output filter handler has completed
successfully, but BEFORE the print statement completes. GDB backtrace is
below. Perl modules CGI.pm and LWP::UserAgent seem to be causal in
generating the seg fault.

Here is the somewhat complicated recipe that produces the seg fault
reliably. 

1. ModPerl::Registry script using CGI.pm header() and a print statement
that includes a comma separated (list) of strings > 8kb.
2. An output filter handler that uses LWP::UserAgent to make an HTTP
request.

Caveats:
    - Only occurs in an Apache child that hasn't already loaded these
modules (CGI, LWP::UserAgent) and dependents.
    - Occurs in single process mode (-X) on both static and dynamically
linked builds.

Example script/filter and system details are below. I can provide more
info if needed. I'm currently testing other module versions. Can anyone
suggest a fix or workaround? 

Thanks!
Ed Eddington
Sr. Software Engr - Web Development
Priority Health - Grand Rapids, MI


GDB BACKTRACE

(gdb) continue
Continuing.

Program received signal SIGSEGV, Segmentation fault.
Perl_do_print (my_perl=0x8497ae0, sv=0x1, fp=0x86ee6c8) at doio.c:1321
1321    doio.c: No such file or directory.
        in doio.c
(gdb) bt
#0  Perl_do_print (my_perl=0x8497ae0, sv=0x1, fp=0x86ee6c8) at
doio.c:1321
#1  0x00375da8 in Perl_pp_print (my_perl=0x8497ae0) at pp_hot.c:624
#2  0x00362973 in Perl_runops_debug (my_perl=0x8497ae0) at dump.c:1452
#3  0x0031d812 in S_call_body (my_perl=0x8497ae0, myop=0xbff8d050,
is_eval=0) at perl.c:2364
#4  0x0031d4dd in Perl_call_sv (my_perl=0x8497ae0, sv=0x0, flags=4) at
perl.c:2282
#5  0x0807a257 in modperl_callback (my_perl=0x8497ae0,
handler=0x92bf1d8, p=0x93522b8, r=0x93522f0, s=0x92c0ef0,
args=0x932c878)
    at modperl_callback.c:100
#6  0x0807a997 in modperl_callback_run_handlers (idx=6, type=4,
r=0x93522f0, c=0x0, s=0x92c0ef0, pconf=0x0, plog=0x0, ptemp=0x0, 
    run_mode=MP_HOOK_RUN_FIRST) at modperl_callback.c:261
#7  0x0807af07 in modperl_callback_per_dir (idx=6, r=0x1,
run_mode=MP_HOOK_RUN_FIRST) at modperl_callback.c:368
#8  0x08074aa1 in modperl_response_handler_run (r=0x93522f0, finish=0)
at mod_perl.c:994
#9  0x08074d2b in modperl_response_handler_cgi (r=0x93522f0) at
mod_perl.c:1089
#10 0x080f5040 in ap_run_handler ()
#11 0x080f579e in ap_invoke_handler ()
#12 0x080c55da in ap_process_request ()
#13 0x080bfa06 in ap_process_http_connection ()
#14 0x08101ab8 in ap_run_process_connection ()
#15 0x08101ea3 in ap_process_connection ()
#16 0x080f38fb in child_main ()
#17 0x080f39d2 in make_child ()
#18 0x080f3af8 in startup_children ()
#19 0x080f3efe in ap_mpm_run ()
#20 0x080fac06 in main ()



EXAMPLE SCRIPT

#!/usr/bin/perl
use strict;
use Carp;

use CGI qw(:standard);

warn "TEST START...";

# doesn't matter if you have this line in the print stmt or not
header(-type=>"text/html");

my $head = '<HTML>';
my $foot = '</html>';
my $string = &string;

print $head,$string,br,$foot;

warn "TEST DONE--------------------------";

sub string {
    my $string;
    for (1..8200) {
        $string.= 'A';
    }
    return $string;
}


EXAMPLE FILTER:

#file:Apache2/SimpleFilter.pm
#--------------------------------
package PH::Apache2::SimpleFilter;

use strict;
use warnings;

use base qw(Apache2::Filter);

use APR::Brigade ();
use APR::Bucket ();

use Apache2::Const -compile => 'OK';
use APR::Const     -compile => ':common';

sub handler : FilterRequestHandler {
    my ($f, $bb) = @_;

    my $bb_ctx = APR::Brigade->new($f->c->pool, $f->c->bucket_alloc);

    while (!$bb->is_empty) {
        my $b = $bb->first;

        $b->remove;

        if ($b->is_eos) {
            $bb_ctx->insert_tail($b);
            last;
        }

        if ($b->read(my $data)) {
            #Do Nothing
            #$data = join "",
            #    map {scalar(reverse $_), "\n"} split "\n", $data;
            $b = APR::Bucket->new($bb->bucket_alloc, $data);
        }
        use LWP::UserAgent;
        my $ua = LWP::UserAgent->new();
        my $uri = 'http://www.yahoo.com';
        my $response = $ua->get($uri);
        warn "LWP got $response";

        $bb_ctx->insert_tail($b);
  }

  my $rv = $f->next->pass_brigade($bb_ctx);
  return $rv unless $rv == APR::Const::SUCCESS;

  Apache2::Const::OK;
}
1;

-----------------------------------------
SYSTEM DETAILS:
-----------------------------------------

mod_perl version 2.000001
LWP - 5.803
LWP::UserAgent - 2.03
CGI - 3.25
Apache2::Request - 2.08


$ uname -a
Linux molly 2.6.9-42.ELsmp #1 SMP Wed Jul 12 23:27:17 EDT 2006 i686 i686
i386 GNU/Linux


DYNAMIC APACHE

$ /opt/apache2/bin/httpd -l
Compiled in modules:
  core.c
  prefork.c
  http_core.c
  mod_so.c

$ /opt/apache2/bin/httpd -V
Server version: Apache/2.0.59
Server built:   Jul 28 2006 15:42:08
Server's Module Magic Number: 20020903:12
Server loaded:  APR 0.9.12, APR-UTIL 0.9.12
Compiled using: APR 0.9.12, APR-UTIL 0.9.12
Architecture:   32-bit
Server compiled with....
 -D APACHE_MPM_DIR="server/mpm/prefork"
 -D APR_HAS_SENDFILE
 -D APR_HAS_MMAP
 -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
 -D APR_USE_SYSVSEM_SERIALIZE
 -D APR_USE_PTHREAD_SERIALIZE
 -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 -D APR_HAS_OTHER_CHILD
 -D AP_HAVE_RELIABLE_PIPED_LOGS
 -D HTTPD_ROOT="/opt/apache2"
 -D SUEXEC_BIN="/opt/apache2/bin/suexec"
 -D DEFAULT_PIDLOG="logs/httpd.pid"
 -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
 -D DEFAULT_LOCKFILE="logs/accept.lock"
 -D DEFAULT_ERRORLOG="logs/error_log"
 -D AP_TYPES_CONFIG_FILE="conf/mime.types"
 -D SERVER_CONFIG_FILE="conf/httpd.conf"


STATIC APACHE (built with debug flags)

$ /opt/apache2-debug/bin/httpd -l
Compiled in modules:
  core.c
  mod_perl.c
  mod_access.c
  mod_auth.c
  mod_include.c
  mod_log_config.c
  mod_env.c
  mod_headers.c
  mod_setenvif.c
  mod_proxy.c
  proxy_connect.c
  proxy_ftp.c
  proxy_http.c
  mod_ssl.c
  prefork.c
  http_core.c
  mod_mime.c
  mod_dav.c
  mod_status.c
  mod_autoindex.c
  mod_asis.c
  mod_cgi.c
  mod_dav_fs.c
  mod_negotiation.c
  mod_dir.c
  mod_imap.c
  mod_actions.c
  mod_userdir.c
  mod_alias.c
  mod_rewrite.c
  mod_so.c

$ /opt/apache2-debug/bin/httpd -V
Server version: Apache/2.0.59
Server built:   Nov  3 2006 13:36:26
Server's Module Magic Number: 20020903:12
Server loaded:  APR 0.9.12, APR-UTIL 0.9.12
Compiled using: APR 0.9.12, APR-UTIL 0.9.12
Architecture:   32-bit
Server compiled with....
 -D APACHE_MPM_DIR="server/mpm/prefork"
 -D APR_HAS_SENDFILE
 -D APR_HAS_MMAP
 -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
 -D APR_USE_SYSVSEM_SERIALIZE
 -D APR_USE_PTHREAD_SERIALIZE
 -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 -D APR_HAS_OTHER_CHILD
 -D AP_HAVE_RELIABLE_PIPED_LOGS
 -D HTTPD_ROOT="/opt/apache2-debug"
 -D SUEXEC_BIN="/opt/apache2-debug/bin/suexec"
 -D DEFAULT_PIDLOG="logs/httpd.pid"
 -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
 -D DEFAULT_LOCKFILE="logs/accept.lock"
 -D DEFAULT_ERRORLOG="logs/error_log"
 -D AP_TYPES_CONFIG_FILE="conf/mime.types"
 -D SERVER_CONFIG_FILE="conf/httpd.conf"

$ /usr/bin/ldd  /opt/apache2/bin/httpd
        libz.so.1 => /usr/lib/libz.so.1 (0x00ab2000)
        libssl.so.4 => /lib/libssl.so.4 (0x00129000)
        libcrypto.so.4 => /lib/libcrypto.so.4 (0x006d7000)
        libgssapi_krb5.so.2 => /usr/lib/libgssapi_krb5.so.2 (0x00de9000)
        libkrb5.so.3 => /usr/lib/libkrb5.so.3 (0x00227000)
        libcom_err.so.2 => /lib/libcom_err.so.2 (0x00de4000)
        libk5crypto.so.3 => /usr/lib/libk5crypto.so.3 (0x0028e000)
        libresolv.so.2 => /lib/libresolv.so.2 (0x00ac4000)
        libaprutil-0.so.0 => /opt/apache2/lib/libaprutil-0.so.0
(0x00111000)
        libexpat.so.0 => /opt/apache2/lib/libexpat.so.0 (0x0099d000)
        libapr-0.so.0 => /opt/apache2/lib/libapr-0.so.0 (0x00a54000)
        librt.so.1 => /lib/tls/librt.so.1 (0x002b1000)
        libm.so.6 => /lib/tls/libm.so.6 (0x00963000)
        libcrypt.so.1 => /lib/libcrypt.so.1 (0x002fc000)
        libnsl.so.1 => /lib/libnsl.so.1 (0x002cd000)
        libpthread.so.0 => /lib/tls/libpthread.so.0 (0x0015d000)
        libdl.so.2 => /lib/libdl.so.2 (0x0095d000)
        libc.so.6 => /lib/tls/libc.so.6 (0x00830000)
        /lib/ld-linux.so.2 (0x00817000)


$ /opt/perl-5.8/bin/perl -V
Summary of my perl5 (revision 5 version 8 subversion 7) configuration:
  Platform:
    osname=linux, osvers=2.4.21-32.0.1.elsmp,
archname=i686-linux-thread-multi
    uname='linux molly 2.4.21-32.0.1.elsmp #1 smp tue may 17 17:52:23
edt 2005 i686 i686 i386 gnulinux '
    config_args='-der'
    hint=previous, useposix=true, d_sigaction=define
    usethreads=define use5005threads=undef useithreads=define
usemultiplicity=define
    useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
    use64bitint=undef use64bitall=undef uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -g -fPIC
-I/opt/perl-5.8/local/include -DDEBUGGING -fno-strict-aliasing -pipe
-I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-g -O2 ',
    cppflags='-D_REENTRANT -D_GNU_SOURCE -g -fPIC
-I/opt/perl-5.8/local/include -DDEBUGGING -fno-strict-aliasing -pipe
-I/usr/local/include -D_REENTRANT -D_GNU_SOURCE -g -fPIC
-I/opt/perl-5.8/local/include -DDEBUGGING -fno-strict-aliasing -pipe
-I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'
    ccversion='', gccversion='3.2.3 20030502 (Red Hat Linux 3.2.3-52)',
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 /usr/ccs/lib
    libs=-lnsl -ldb -ldl -lm -lcrypt -lutil -lpthread -lc
    perllibs=-lnsl -ldl -lm -lcrypt -lutil -lpthread -lc
    libc=/lib/libc-2.3.2.so, so=so, useshrplib=true, libperl=libperl.so
    gnulibc_version='2.3.2'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E
-Wl,-rpath,/opt/perl-5.8/lib/5.8.7/i686-linux-thread-multi/CORE'
    cccdlflags='-fpic', lddlflags='-shared -L/usr/local/lib'


Characteristics of this binary (from libperl): 
  Compile-time options: DEBUGGING MULTIPLICITY USE_ITHREADS
                        USE_LARGE_FILES PERL_IMPLICIT_CONTEXT
  Built under linux
  Compiled at Sep 12 2005 12:52:00
  @INC:
    /opt/perl-5.8/lib/5.8.7/i686-linux-thread-multi
    /opt/perl-5.8/lib/5.8.7
    /opt/perl-5.8/lib/site_perl/5.8.7/i686-linux-thread-multi
    /opt/perl-5.8/lib/site_perl/5.8.7
    /opt/perl-5.8/lib/site_perl
    .


HTTPD2.CONF (relavent pieces included in order)

PerlOutputFilterHandler PH::Apache2::SimpleFilter
...
    <Location /prog >
        ProxyPass !
        SetHandler perl-script
        PerlResponseHandler ModPerl::Registry
        Options ExecCGI
    </Location>


** ** **  PRIVILEGED AND CONFIDENTIAL  ** ** **
This email transmission contains privileged and confidential information intended only for the use of the individual or entity named above.  Any unauthorized review, use, disclosure or distribution is prohibited and may be a violation of law.  If you are not the intended recipient or a person responsible for delivering this message to an intended recipient, please delete the email and immediately notify the sender via the email return address or mailto:postmaster@priority-health.com.  Thank you.

- end -


Re: [MP2] Seg Fault in Registry script "print" using output filter handler

Posted by Ed Eddington <ed...@gmail.com>.
I found another component to the seg fault. I am using a dynamically linked
mod_deflate output filter as well (will test with static). I get no seg
fault when I comment out the DEFLATE line in the Apache config. (Sorry, I
hadn't noticed this piece of the puzzle.)

   LoadModule deflate_module      /opt/apache2/modules/mod_deflate.so
   ...
    <Location /prog >
        SetHandler perl-script
        PerlResponseHandler ModPerl::Registry
        Options ExecCGI
        AddOutputFilterByType DEFLATE text/html text/plain text/xml
    </Location>

Re: [MP2] Seg Fault in Registry script "print" using output filter handler

Posted by Ed Eddington <ed...@gmail.com>.
The workarounds (viable to me) that prevent the seg fault descirbed below
are:

1. Use LWP::UserAgent within a startup.pl (need to actually make a complete
HTTP request, not just 'use')
2. Use WWW:Curl instead of LWP::UserAgent in the output filter

One of the keys to the seg fault seems to be the use of LWP::UserAgent
within a bucket brigade filter. The seg fault occurs if Perl hasn't yet
loaded this module (and friends). After the filter runs successfully - seg
fault. Interestingly though, the other factors described are all necessary:
CGI.pm header(), the print statement must have a comma and contain >8k -
which causes the output filter to run during the "print", not after.

Can anyone offer a potential cause for the seg fault? The example code
provided is all straight out of the docs.

Other things to note:
    - This occurs on a pre-forking mpm running in single process mode -X
    - The LWP request is not hitting the same server

Thanks,
Ed Eddington


On 11/15/06, Ed.Eddington@priorityhealth.com <
Ed.Eddington@priorityhealth.com> wrote:
>
>
> I'm getting seg faults within "print" of ModPerl::Registry script while
> using an output filter handler. The output filter is run during the script's
> "print" statement when the printed string is > ~8kb. Debugging shows the seg
> fault occurs AFTER the output filter handler has completed successfully, but
> BEFORE the print statement completes. GDB backtrace is below. Perl modules
> CGI.pm and LWP::UserAgent seem to be causal in generating the seg fault.
>
> Here is the somewhat complicated recipe that produces the seg fault
> reliably.
>
> 1. ModPerl::Registry script using CGI.pm header() and a print statement
> that includes a comma separated (list) of strings > 8kb.
>
> 2. An output filter handler that uses LWP::UserAgent to make an HTTP
> request.
>
> Caveats:
>     - Only occurs in an Apache child that hasn't already loaded these
> modules (CGI, LWP::UserAgent) and dependents.
>     - Occurs in single process mode (-X) on both static and dynamically
> linked builds.
>
> Example script/filter and system details are below. I can provide more
> info if needed. I'm currently testing other module versions. Can anyone
> suggest a fix or workaround?
>
> Thanks!
> *Ed Eddington*
> Sr. Software Engr - Web Development
> Priority Health - Grand Rapids, MI
>