Re: mod_perl 2.0 and print/send_http_header method SEGFAULT
On Thu, Jan 16, 2003 at 10:27:38AM +1100, Stas Bekman wrote: Cool. Now can you please send the shortest possible example that you still get the SEGFAULT with, so I can reproduce it and fix? Thanks. I finally got a working apache2+mod_perl working in my $HOME dir (I could not find the core files of the RedHat httpd, problems with uid permission i guess) So here are the backtraces. I included two backtraces : - the first one is for the crash with $r-send_http_header() - the second one is for the crash with $r-print() when I remove the send_http_header() statement The config in httpd.conf : # mod_perl LoadModule perl_module modules/mod_perl.so PerlModule Apache2 PerlTransHandler Apache::SegFault # proxy LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_ftp_module modules/mod_proxy_ftp.so LoadModule proxy_http_module modules/mod_proxy_http.so LoadModule proxy_connect_module modules/mod_proxy_connect.so ProxyRequests On Proxy * Order deny,allow Deny from all Allow from localhost /Proxy Then I issue a simple request with : echo -ne GET http://perl.apache.org HTTP/1.0\n\n | nc localhost 8081 -8-- Start Bug Report 8-- 1. Problem Description: BEGIN package Apache::SegFault; use strict; use Apache::compat; use Apache::RequestRec; use Apache::RequestIO; use Apache::RequestUtil; use Apache::Const; use Apache::ServerUtil; use Apache::Response; use Apache::URI; use APR::Table; sub handler { my $r = shift; return Apache::DECLINED unless( $r-proxyreq ); print STDERR Good, this is a proxyreq ...\n; return Apache::DECLINED unless( $r-method eq GET ); print STDERR Good, this is a GET method ...\n; my $content = htmlbodyplop/body/html; my %headers_out; $headers_out{ 'Content-length' } = length( $content ); $headers_out{ 'Content-type' } = 'text/html'; foreach (keys %headers_out) { $r-headers_out-{$_} = $headers_out{$_}; } $r-content_type( $headers_out{ 'Content-type' } ); print STDERR -- send/print --\n; # -- SEGFAULT here $r-send_http_header(); # -- or here, when removing the send_http_header() line above $r-print( $content ); print STDERR -- end --\n; return Apache::OK; } 1; END 2. Used Components and their Configuration: *** using lib/Apache/BuildConfig.pm *** Makefile.PL options: MP_APXS= /home/jauge/httpd/bin/apxs MP_DEBUG = 1 MP_GENERATE_XS = 1 MP_LIBNAME = mod_perl MP_MAINTAINER = 1 MP_TRACE = 1 MP_USE_DSO = 1 MP_USE_STATIC = 1 *** /home/jauge/httpd/bin/httpd -V Server version: Apache/2.0.43 Server built: Jan 16 2003 15:38:17 Server's Module Magic Number: 20020903:0 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 -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=/home/jauge/httpd -D SUEXEC_BIN=/home/jauge/httpd/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/perl -V Summary of my perl5 (revision 5.0 version 8 subversion 0) configuration: Platform: osname=linux, osvers=2.4.18-11smp, archname=i386-linux-thread-multi uname='linux daffy.perf.redhat.com 2.4.18-11smp #1 smp thu aug 15 06:41:59 edt 2002 i686 i686 i386 gnulinux ' config_args='-des -Doptimize=-O2 -march=i386 -mcpu=i686 -Dmyhostname=localhost -Dperladmin=root@localhost -Dcc=gcc -Dcf_by=Red Hat, Inc. -Dinstallprefix=/usr -Dprefix=/usr -Darchname=i386-linux -Dvendorprefix=/usr -Dsiteprefix=/usr -Duseshrplib -Dusethreads -Duseithreads -Duselargefiles -Dd_dosuid -Dd_semctl_semun -Di_db -Ui_ndbm -Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Duseperlio -Dinstallusrbinperl -Ubincompat5005 -Uversiononly -Dpager=/usr/bin/less -isr' hint=recommended, 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='gcc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm', optimize='-O2 -march=i386 -mcpu=i686', cppflags='-D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -I/usr/include/gdbm' ccversion='', gccversion='3.2 20020822 (Red Hat Linux Rawhide 3.2-5)', gccosandvers='' intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
Re: mod_perl 2.0 and print/send_http_header method SEGFAULT
Jérôme Augé wrote: On Thu, Jan 16, 2003 at 10:27:38AM +1100, Stas Bekman wrote: Cool. Now can you please send the shortest possible example that you still get the SEGFAULT with, so I can reproduce it and fix? Thanks. I finally got a working apache2+mod_perl working in my $HOME dir (I could not find the core files of the RedHat httpd, problems with uid permission i guess) So here are the backtraces. I included two backtraces : - the first one is for the crash with $r-send_http_header() - the second one is for the crash with $r-print() when I remove the send_http_header() statement The problem is that you were calling these functions before the response phase (PerlTransHandler in your case), hence triggered the segfaults. I've fixed those in cvs. Now if you call any of these functions too early mod_perl will croak. Please verify with the latest cvs. To solve your particular case, you need to use: $r-set_handlers(PerlResponseHandler = \response); inside the PerlTransHandler handler, and move all the code that generates the response there. __ 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 2.0 and print/send_http_header method SEGFAULT
On Wed, Jan 15, 2003 at 09:09:37AM +1100, Stas Bekman wrote: I've applied a fix that hopefully cures this thing in cvs. Please try again with the latest cvs version. http://perl.apache.org/download/source.html#2_0_Development_Source_Distribution I installed the CVS version (1.9909) and I still get a SEGFAULT when using $r-send_http_header() or $r-print() ... - I fetched the mod_perl CVS sources then launched : $ perl Makefile.PL MP_APXS=/usr/sbin/apxs $ make $ make install - modified the /etc/httpd/conf.d/perl.conf file - restarted httpd I also tested with the Apache::ProxyPassThru module (from http://perl.apache.org/dist/contrib/ProxyPassThru.pm) I added a use Apache::compat statement, removed the $r-handler()/$r-push_handlers() part and I also get a SEGFAULT when it reach the http_send_header() statement ... --
Re: mod_perl 2.0 and print/send_http_header method SEGFAULT
I grep'ed into the mod_perl sources and found in examples/lib/Apache/HelloWorld.pm that send_http_header does not exists in mod_perl 2.0 and print is not yet implemented. Is this right ? so this could easily explain my problems :) in examples/lib/Apache/HelloWorld.pm : [...] sub handler { my $r = shift; $r-content_type('text/plain'); #send_http_header API function does not exist in 2.0 $r-puts(__PACKAGE__); #print not yet implemented return Apache::OK; } [...] --
Re: mod_perl 2.0 and print/send_http_header method SEGFAULT
Jérôme Augé wrote: On Wed, Jan 15, 2003 at 09:09:37AM +1100, Stas Bekman wrote: I've applied a fix that hopefully cures this thing in cvs. Please try again with the latest cvs version. http://perl.apache.org/download/source.html#2_0_Development_Source_Distribution Since you've never sent the backtrace of SEGFAULT, as explained here: http://perl.apache.org/docs/2.0/user/help/help.html#Reporting_Problems there can be more than one problem. I've fixed one, but there can be more lurking behind the first one. So if you can send the backtrace, that will help a lot. I installed the CVS version (1.9909) and I still get a SEGFAULT when using $r-send_http_header() or $r-print() ... - I fetched the mod_perl CVS sources then launched : $ perl Makefile.PL MP_APXS=/usr/sbin/apxs $ make $ make install - modified the /etc/httpd/conf.d/perl.conf file - restarted httpd Cool. Now can you please send the shortest possible example that you still get the SEGFAULT with, so I can reproduce it and fix? Thanks. I also tested with the Apache::ProxyPassThru module (from http://perl.apache.org/dist/contrib/ProxyPassThru.pm) I added a use Apache::compat statement, removed the $r-handler()/$r-push_handlers() part and I also get a SEGFAULT when it reach the http_send_header() statement ... send_http_header is indeed doesn't exist in 2.0, but implemented in Apache::compat and should work just fine, as it's exercised in many tests: grep -Ir send_http_header t t/compat/request_body.t:# $r-send_http_header('text/plain'); t/compat/request_body.t:q{$r-send_http_header('text/plain')} t/response/TestCompat/request_body.pm:$r-send_http_header('text/plain'); t/response/TestCompat/apache.pm:$r-send_http_header('text/plain'); t/response/TestCompat/apache_file.pm:$r-send_http_header('text/plain'); t/response/TestCompat/apache_table.pm:$r-send_http_header('text/plain'); t/response/TestCompat/apache_util.pm:$r-send_http_header('text/plain'); t/response/TestCompat/request.pm:$r-send_http_header('text/plain'); __ 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 2.0 and print/send_http_header method SEGFAULT
Jérôme Augé wrote: I grep'ed into the mod_perl sources and found in examples/lib/Apache/HelloWorld.pm that send_http_header does not exists in mod_perl 2.0 and print is not yet implemented. Is this right ? so this could easily explain my problems :) It's an old example, I've removed it. in examples/lib/Apache/HelloWorld.pm : [...] sub handler { my $r = shift; $r-content_type('text/plain'); #send_http_header API function does not exist in 2.0 $r-puts(__PACKAGE__); #print not yet implemented return Apache::OK; } [...] -- __ 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 2.0 and print/send_http_header method SEGFAULT
On Tue, Jan 14, 2003 at 12:32:29PM +1100, Stas Bekman wrote: Location /plop/ SetHandler perl-script PerlHeaderParserHandler Apache::Plop /Location Well, this is not really what I want to do ... I would like to catch all the proxy request and apply modifications to the requested document before forwarding the answer back to the client. That's why I used the PerlTransHandler which is global and not tied to a particular directory. Now to your code: 1. You can't push_handlers when you are inside a response handler. Use PerlHeaderParserHandler instead 2. $r-headers_in-do() expects a return value and will abort on 0; see the attached code also it should be: $request-header( $_[0] = $_[1] ); instead of: $request-header( {$_[0]} = $_[1] ); have you looked at error_log? You'd have seen that error reported. 3. This is not good: my $request = HTTP::Request-new( $r-method, $r-uri); since you don't the whole url. Use this instead: my $request = HTTP::Request-new( $r-method, $r-construct_url); this requires 'use Apache::URI' 4. Finally I've used a special header: (which can be anything) $request-header( GetReal = 1 ); to know that now I'm inside the real request. Thanks for your remarks. I installed modperl-1.99_08 and I keep getting SEGFAULT with my original code ... I think I'll try to get it working first on mod_perl 1.x then get back to modperl 2 --
Re: mod_perl 2.0 and print/send_http_header method SEGFAULT
Jérôme Augé wrote: Hi, I'm beginning with mod_perl (mod_perl-1.99_05 + Apache 2.0.40 from RedHat 8.0) and I want to write a module for rewriting the documents that passes through the Apache proxy. So, I looked at the Apache::AdBlocker (http://perl.apache.org/docs/tutorials/tips/mod_perl_tricks/mod_perl_tricks.html#A_Banner_Ad_Blocker) module and I'm facing some problems for writing the content of the documents back to the client. My main problem is that I get a SEGFAULT when calling the $r-print() or $r-send_http_header() method. I get the request, copy the headers from headers_in, make my own request with LWP, copy the headers to headers_out, then it SEGFAULT when writing the document ... Are this methods deprecated/not fully implemented ? what is the correct way to write data to the client ? The other problem is that if I use the $r-push_handlers(PerlHandler = \proxy_handler) mechanism, my proxy_handler() function is never called, so I do the work directly into the handler sub, is this ok ? I attached my test module below (I register it with a PerlTransHandler Apache::Plop statement in httpd.conf) After making your example work, I don't see any segfaults. Please try again with modperl-1.99_08 which was released a few days ago. I've attached Plop.pm that apparently works. Hope that this is what you wanted to accomplish. I've used the following config: Location /plop/ SetHandler perl-script PerlHeaderParserHandler Apache::Plop /Location Now to your code: 1. You can't push_handlers when you are inside a response handler. Use PerlHeaderParserHandler instead 2. $r-headers_in-do() expects a return value and will abort on 0; see the attached code also it should be: $request-header( $_[0] = $_[1] ); instead of: $request-header( {$_[0]} = $_[1] ); have you looked at error_log? You'd have seen that error reported. 3. This is not good: my $request = HTTP::Request-new( $r-method, $r-uri); since you don't the whole url. Use this instead: my $request = HTTP::Request-new( $r-method, $r-construct_url); this requires 'use Apache::URI' 4. Finally I've used a special header: (which can be anything) $request-header( GetReal = 1 ); to know that now I'm inside the real request. Hope that this helps. Also you might want to use a sub-request rather than a heavy weighted LWP to accomplish what you do. __ 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 package Apache::Plop; use strict; use Apache::RequestRec; use Apache::RequestIO; use Apache::RequestUtil; use Apache::Const; use Apache::ServerUtil; use Apache::Response; use Apache::URI; use APR::Table; use LWP::UserAgent; my $ua = LWP::UserAgent-new(); sub handler { my $r = shift; if( $r-proxyreq ) { return Apache::DECLINED; } print STDERR Good, this is a proxyreq ...\n; $r-handler(perl-script); #ok, let's do it $r-push_handlers(PerlResponseHandler = \proxy_handler); return Apache::OK; } sub proxy_handler { my $r = shift; if( $r-method ne GET ) { return Apache::DECLINED; } print STDERR Good, this is a GET method ...\n; if ( ($r-headers_in-get('GetReal')||0) == 1) { $r-content_type('text/plain'); print hey; return Apache::OK; } # prepare the real request my $request = HTTP::Request-new( $r-method, $r-construct_url); # copy headers from client request my %headers_in; print STDERR -- client headers --\n; $r-headers_in()-do( sub { warn $_[0]: $_[1]\n; $headers_in{ $_[0] } = $_[1]; $request-header( $_[0] = $_[1] ); return 1; } ); print STDERR -- end --\n; # make the real request myself $ua-agent( $headers_in{ 'User-Agent' } ); $request-header( GetReal = 1 ); warn $request-as_string; my $response = $ua-request( $request ); if ( ! $response-is_success() ) { print STDERR == ERROR ==\n; return Apache::DECLINED; } print STDERR -- server headers --\n; my %headers_out; $response-headers()-scan( sub { print STDERR $_[0]: $_[1]\n; $headers_out{$_[0]} = $_[1]; } ); print STDERR -- end --\n; # simply override the content my $content = $response-content; $content = htmlbodyplop/body/html; # adjust the headers for the new content $headers_out{ 'Content-length' } = length( $content ); $headers_out{ 'Content-type' } = 'text/html'; # copy the modified response headers back to Apache foreach (keys %headers_out) { $r-headers_out-{$_} = $headers_out{$_}; }
Re: mod_perl 2.0 and print/send_http_header method SEGFAULT
Stas Bekman wrote: Jérôme Augé wrote: [...] After making your example work, I don't see any segfaults. Please try again with modperl-1.99_08 which was released a few days ago. [...] 1. You can't push_handlers when you are inside a response handler. Use PerlHeaderParserHandler instead I've played some more with your original code and did find the segfault you were talking about. Though it happens when you use push_handlers in the same phase to which you push to. Hence I didn't see it in the code that I've fixed. So most likely your _05 version will work just fine with the version that I've posted in my original reply. Meanwhile I'm looking at how it's the best to prevent from the segfault to happen and push_handlers() be used in a wrong place. __ 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