--- a/Changes +++ a/Changes @@ -10,6 +10,69 @@ Also refer to the Apache::Test changes log file, at Apache-Test/Changes =over 3 +=item 2.0.6-dev + +Adopt modperl_pcw.c changes from httpd24 branch. [Torsten Foertsch] + +Pool cleanup functions must not longjmp. Catch these exceptions and turn +them into warnings. [Torsten Foertsch] + +Fix a race condition in our tipool management. +See http://www.gossamer-threads.com/lists/modperl/dev/104026 +Patch submitted by: SalusaSecondus +Reviewed by: Torsten Foertsch + +Ensure that MP_APXS is set when building on Win32 with MP_AP_PREFIX, +otherwise the bundled Reload and SizeLimit builds will fail to find a +properly configured Test environment. +[Steve Hay] + +Fix a few REFCNT bugs. +Patch submitted by: Niko Tyni +Reviewed by: Torsten Foertsch + +Correct the initialization of the build config in ModPerl::MM. The global +variable was only being set once on loading the module, which was before +Apache2::BuildConfig.pm had been written, leading to cwd and MP_LIBNAME +being unset when writing the Reload and SizeLimit makefiles. +[Steve Hay] + +Discover apr-2-config from Apache 2.4 onwards. [Gozer] + +Apache 2.4 and onwards doesn't require linking the MPM module directly in +the httpd binary anymore. APXS lost the MPM_NAME query, so we can't assume +a given MPM anymore. Introduce a fake MPM 'dynamic' to represent this. +[Torsten Foertsch, Gozer] + +Perl 5.14 brought a few changes in Perl_sv_dup() that made a threaded apache +segfault while cloning interpreters. +[Torsten Foertsch] + +PerlIOApache_flush() and mpxs_Apache2__RequestRec_rflush() now no longer throw +exceptions when modperl_wbucket_flush() fails if the failure was just a reset +connection or an aborted connection. The failure is simply logged to the error +log instead. This should fix cases of httpd.exe crashing when users press the +Stop button in their web browsers. +[Steve Hay] + +Fixed a few issues that came up with LWP 6.00: +- t/response/TestAPI/request_rec.pm assumes HTTP/1.0 but LWP 6 uses 1.1 +- t/api/err_headers_out.t fails due to a bug somewhere in LWP 6 +- t/filter/TestFilter/out_str_reverse.pm sends the wrong content-length header +[Torsten Foertsch] + +Bugfix: Apache2::ServerUtil::get_server{description,banner,version} cannot +be declared as perl constants or they won't reflect added version components +if Apache2::ServerUtil is loaded before the PostConfig phase. Now, they +are ordinary perl functions. [Torsten Foertsch] + +Check for the right ExtUtils::Embed version during build [Torsten Foertsch] + +Take a lesson from rt.cpan.org #66085 and pass LD_LIBRARY_PATH if mod_env +is present. Should prevent test failures on some platforms. +[Fred Moyer] + + =item 2.0.5 February 7, 2011 The mod_perl PMC dedicates this release of mod_perl to Randy Kobes, who --- a/Makefile.PL +++ a/Makefile.PL @@ -52,6 +52,7 @@ my $code = ModPerl::Code->new; sub UNATTENDED() { $build->{MP_PROMPT_DEFAULT} || ! -t STDIN } +# may populate $build->{MP_APXS} win32_fetch_apxs() if WIN32; configure(); @@ -241,6 +242,8 @@ EOI } } + $build->{$_} and $ENV{$_} = $build->{$_} for (qw/MP_APXS MP_AP_PREFIX/); + unless ($build->{MP_APXS} or $build->{MP_AP_PREFIX}) { my $ok = 0; for my $path ($build->find) { @@ -621,6 +624,8 @@ sub win32_fetch_apxs { my $script = catfile($build->{cwd}, 'build', 'win32_fetch_apxs'); my @args = ($^X, $script, "--with-apache2=$prefix"); system(@args) == 0 or die "system @args failed: $?"; + my $apxs = catfile($prefix, 'bin', 'apxs.bat'); + $build->{MP_APXS} = $apxs if -e $apxs; } @@ -777,7 +782,7 @@ PASSENV = $env EOF } - return $preamble . <<'EOF'; + $preamble .= <<'EOF'; TEST_VERBOSE = 0 TEST_FILES = @@ -789,20 +794,26 @@ run_tests : test_clean $(PASSENV) \ $(FULLPERL) -I$(INST_ARCHLIB) -I$(INST_LIB) \ t/TEST -bugreport -verbose=$(TEST_VERBOSE) $(TEST_FILES) - $(MAKE) -k run_subtests run_subtests :: - $(MAKE) -C ModPerl-Registry test + cd ModPerl-Registry && $(MAKE) test run_subtests :: - $(MAKE) -C Apache-Reload test + cd Apache-Reload && $(MAKE) test + +EOF + $preamble .= <<'EOF' unless $build->mpm_is_threaded(); run_subtests :: - $(MAKE) -C Apache-SizeLimit test + cd Apache-SizeLimit && $(MAKE) test + +EOF -test :: pure_all run_tests test_clean + $preamble .= <<'EOF'; +test :: pure_all run_tests run_subtests EOF + return $preamble; } sub MY::postamble { --- a/RELEASE +++ a/RELEASE @@ -55,7 +55,7 @@ Instructions for mod_perl 2.0 Release Manager to the modperl/dev list (may be longer to give most people a chance to catch up). no need to tag this package - Subject: [RELEASE CANDIDATE]: mod_perl-2.0.5 RC\d+ + Subject: [RELEASE CANDIDATE]: mod_perl-2.0.6 RC\d+ 2a. if problems are detected during stage 2, repeat stages 1 and 2. @@ -75,61 +75,63 @@ Instructions for mod_perl 2.0 Release Manager % make -n tag d. commit Changes README Makefile.PL - % svn ci -m "Releasing 2.0.5" Changes README Makefile.PL + % svn ci -m "Releasing 2.0.6" Changes README Makefile.PL e. tag % make tag + XXXX: See BRANCHING for the steps to include the proper tagged externals XXXX: This needs to be fixed, and updated, developer beware its outdated and possibly wrong f. Update the svn:externals in the new tag (you can't propedit remotely yet in svn) - % svn co https://svn.apache.org/repos/asf/perl/modperl/tags/2_0_5 - % svn propedit svn:externals 2_0_5 + % svn co https://svn.apache.org/repos/asf/perl/modperl/tags/2_0_6 + % svn propedit svn:externals 2_0_6 Update the Apache-Test line to current revision % svn info https://svn.apache.org/repos/asf/perl/Apache-Test/trunk | grep "Last Changed Rev" Update the docs line to the current tag. It should look like: - % svn propget svn:externals 2_0_5 + % svn propget svn:externals 2_0_6 Apache-Test -r 608229 https://svn.apache.org/repos/asf/perl/Apache-Test/trunk - docs https://svn.apache.org/repos/asf/perl/modperl/docs/tags/2_0_5/src/docs/2.0 + docs https://svn.apache.org/repos/asf/perl/modperl/docs/tags/2_0_6/src/docs/2.0 - % svn ci -m "Releasing 2.0.5" + % svn ci -m "Releasing 2.0.6" g. create the final package % make dist h. test the final package again at least once -4. Release the package and update links (e.g. mod_perl-2.0.5.tar.gz) +4. Release the package and update links (e.g. mod_perl-2.0.6.tar.gz) - a. upload to people.apache.org:/www/perl.apache.org/dist/ + a. upload to people.apache.org:/www/perl.apache.org/dist/ - ask the PMC + chair to give you the needed permissions if you do not have them. - % scp mod_perl-2.0.5.tar.gz people.apache.org:/www/perl.apache.org/dist/ + % scp mod_perl-2.0.6.tar.gz people.apache.org:/www/perl.apache.org/dist/ b. ssh to people.apache.org, unpack the package, update symlinks to the tar ball and unpacked distro: % ssh people.apache.org % cd /www/perl.apache.org/dist/ - % ln -sf mod_perl-2.0.5.tar.gz mod_perl-2.0-current.tar.gz - % tar -xzvf mod_perl-2.0.5.tar.gz + % ln -sf mod_perl-2.0.6.tar.gz mod_perl-2.0-current.tar.gz + % tar -xzvf mod_perl-2.0.6.tar.gz % rm /www/perl.apache.org/dist/mod_perl-2.0-current - % ln -sf mod_perl-2.0.5 mod_perl-2.0-current + % ln -sf mod_perl-2.0.6 mod_perl-2.0-current c. archive older releases (keep current + one prior release) - % mv /www/perl.apache.org/dist/mod_perl-2.0.3.tar.gz \ + % mv /www/perl.apache.org/dist/mod_perl-2.0.4.tar.gz \ /www/perl.apache.org/dist/old - % mv /www/perl.apache.org/dist/mod_perl-2.0.3.tar.gz.asc \ + % mv /www/perl.apache.org/dist/mod_perl-2.0.4.tar.gz.asc \ /www/perl.apache.org/dist/old - % rm -rf /www/perl.apache.org/dist/mod_perl-2.0.3 + % rm -rf /www/perl.apache.org/dist/mod_perl-2.0.4 d. update the version and release date in the docs: % vi modperl-docs/src/download/index_top.html % vi modperl-docs/doap_Perl.rdf and commit. - % svn ci -m "Releasing 2.0.5" \ + % svn ci -m "Releasing 2.0.6" \ modperl-docs/src/download/index_top.html \ modperl-docs/doap_Perl.rdf @@ -139,6 +141,8 @@ Instructions for mod_perl 2.0 Release Manager % /home/perlwww/apache.org/modperl-docs/bin/site_build + You may need to sudo -H -u perlwww to cleanup any svn locks. + 5. Upload the package to CPAN 6. Tarball signing @@ -148,27 +152,27 @@ Instructions for mod_perl 2.0 Release Manager a. sign your local copy of the tarball: - % gpg --detach-sign --armor mod_perl-2.0.5.tar.gz + % gpg --detach-sign --armor mod_perl-2.0.6.tar.gz - % pgps -b --armor mod_perl-2.0.5.tar.gz + % pgps -b --armor mod_perl-2.0.6.tar.gz b. upload the generated sig file to people.apache.org: - % scp mod_perl-2.0.5.tar.gz.asc people.apache.org:/www/perl.apache.org/dist/ + % scp mod_perl-2.0.6.tar.gz.asc people.apache.org:/www/perl.apache.org/dist/ % ssh people.apache.org % cd /www/perl.apache.org/dist/ - % chmod 0664 mod_perl-2.0.5.tar.gz.asc - % ln -sf mod_perl-2.0.5.tar.gz.asc mod_perl-2.0-current.tar.gz.asc + % chmod 0664 mod_perl-2.0.6.tar.gz.asc + % ln -sf mod_perl-2.0.6.tar.gz.asc mod_perl-2.0-current.tar.gz.asc c. ask one of the other developers to double check the signature file and tarball: download both files and verify the signature: - http://perl.apache.org/dist/mod_perl-2.0.5.tar.gz.asc - http://perl.apache.org/dist/mod_perl-2.0.5.tar.gz + http://perl.apache.org/dist/mod_perl-2.0.6.tar.gz.asc + http://perl.apache.org/dist/mod_perl-2.0.6.tar.gz - % gpg --verify mod_perl-2.0.5.tar.gz.asc + % gpg --verify mod_perl-2.0.6.tar.gz.asc - % pgpv mod_perl-2.0.5.tar.gz.asc + % pgpv mod_perl-2.0.6.tar.gz.asc d. make sure that the files you just created are group rw so all the dist admins can make changes: @@ -182,10 +186,10 @@ Instructions for mod_perl 2.0 Release Manager a. unpack the package, update symlinks to the tarball and unpacked distro: % cd /www/www.apache.org/dist/perl/ - % cp /www/perl.apache.org/dist/mod_perl-2.0.5.tar.gz* . - % tar -xzvf mod_perl-2.0.5.tar.gz - % mv mod_perl-2.0.3.tar.gz* /www/archive.apache.org/dist/perl/ - % rm -rf mod_perl-2.0.3 + % cp /www/perl.apache.org/dist/mod_perl-2.0.6.tar.gz* . + % tar -xzvf mod_perl-2.0.6.tar.gz + % mv mod_perl-2.0.4.tar.gz* /www/archive.apache.org/dist/perl/ + % rm -rf mod_perl-2.0.4 b. make sure that the files you just created are group rw so @@ -198,11 +202,11 @@ Instructions for mod_perl 2.0 Release Manager a. post ... to the modperl, announce lists Note, to post to announce@, you must be sending from an apache.org address. - Subject: [ANNOUNCE] mod_perl 2.0.5 + Subject: [ANNOUNCE] mod_perl 2.0.6 include - link at perl.apache.org: - http://apache.org/dist/perl/mod_perl-2.0.5.tar.gz - http://apache.org/dist/perl/mod_perl-2.0.5.tar.gz.asc (pgp sig) + http://apache.org/dist/perl/mod_perl-2.0.6.tar.gz + http://apache.org/dist/perl/mod_perl-2.0.6.tar.gz.asc (pgp sig) - MD5 sig (as it comes from CPAN upload announce). - the latest Changes @@ -213,7 +217,7 @@ Instructions for mod_perl 2.0 Release Manager b. edit ./Changes: - start a new item with incremented version + '-dev' - =item 2.0.6-dev + =item 2.0.7-dev c. add a release entry in STATUS @@ -224,7 +228,7 @@ Instructions for mod_perl 2.0 Release Manager e. commit the changed files - % svn ci -m "start 2.0.5-dev cycle" Changes lib/mod_perl2.pm \ + % svn ci -m "start 2.0.6-dev cycle" Changes lib/mod_perl2.pm \ STATUS RELEASE 10. Old Versions --- a/STATUS +++ a/STATUS @@ -3,6 +3,7 @@ mod_perl 2.0 STATUS: -*-text-*- Release: -------- + 2.000.05 : Released Feb 07, 2011 2.000.04 : Released Apr 16, 2008 2.000.03 : Released Nov 29, 2006 2.000.02 : Released Oct 20, 2005 --- a/lib/Apache2/Build.pm +++ a/lib/Apache2/Build.pm @@ -27,6 +27,42 @@ use File::Basename; use ExtUtils::Embed (); use File::Copy (); +BEGIN { # check for a sane ExtUtils::Embed + unless ($ENV{MP_USE_MY_EXTUTILS_EMBED}) { + my ($version, $path)=(ExtUtils::Embed->VERSION, + $INC{q{ExtUtils/Embed.pm}}); + my $msg=<<"EOF"; +I have found ExtUtils::Embed $version at + + $path + +This is probably not the right one for this perl version. Please make sure +there is only one version of this module installed and that it is the one +that comes with this perl version. + +If you insist on using the ExtUtils::Embed as is set the environment +variable MP_USE_MY_EXTUTILS_EMBED=1 and try again. + +EOF + if (eval {require Module::CoreList}) { + my $req=$Module::CoreList::version{$]}->{q/ExtUtils::Embed/}; + die "Please repair your Module::CoreList" unless $req; + unless ($version eq $req) { + $msg.=("Details: expecting ExtUtils::Embed $req ". + "(according to Module::CoreList)\n\n"); + die $msg; + } + } + else { + my $req=$Config{privlib}.'/ExtUtils/Embed.pm'; + unless ($path eq $req) { + $msg.="Details: expecting ExtUtils::Embed at $req\n\n"; + die $msg; + } + } + } +} + use constant IS_MOD_PERL_BUILD => grep { -e "$_/Makefile.PL" && -e "$_/lib/mod_perl2.pm" } qw(. ..); @@ -240,7 +276,8 @@ sub caller_package { } my %threaded_mpms = map { $_ => 1 } - qw(worker winnt beos mpmt_os2 netware leader perchild threadpool); + qw(worker winnt beos mpmt_os2 netware leader perchild threadpool + dynamic); sub mpm_is_threaded { my $self = shift; my $mpm_name = $self->mpm_name(); @@ -255,7 +292,15 @@ sub mpm_name { # XXX: hopefully apxs will work on win32 one day return $self->{mpm_name} = 'winnt' if WIN32; - my $mpm_name = $self->apxs('-q' => 'MPM_NAME'); + my $mpm_name; + + # httpd >= 2.3 + if ($self->httpd_version_as_int =~ m/^2[3-9]\d+/) { + $mpm_name = 'dynamic'; + } + else { + $mpm_name = $self->apxs('-q' => 'MPM_NAME'); + } # building against the httpd source dir unless (($mpm_name and $self->httpd_is_source_tree)) { @@ -1108,7 +1153,18 @@ sub apr_bindir { sub apr_generation { my ($self) = @_; - return $self->httpd_version_as_int =~ m/2[1-9]\d+/ ? 1 : 0; + + my $httpd_v = $self->httpd_version_as_int; + + if ($httpd_v =~ m/2[4-9]\d+/) { + return 2; + } + elsif ($httpd_v =~ m/2[1-3]\d+/) { + return 1; + } + else { + return; + } } # returns an array of apr/apu linking flags (--link-ld --libs) if found @@ -1168,7 +1224,8 @@ sub apru_config_path { $self->{$key} = $self->{$mp_key}; } - my $config = $self->apr_generation ? "$what-1-config" : "$what-config"; + my $apr_generation = $self->apr_generation; + my $config = $apr_generation ? "$what-${apr_generation}-config" : "$what-config"; if (!$self->{$key}) { my @tries = (); @@ -1536,8 +1593,11 @@ sub make_tools { require ExtUtils::MakeMaker; my $mm = bless { @mm_init_vars }, 'MM'; - $mm->init_main; - $mm->init_others; + + # Fake initialize MakeMaker + foreach my $m (qw(init_main init_others init_tools)) { + $mm->$m() if $mm->can($m); + } for (qw(rm_f mv ld ar cp test_f)) { my $val = $mm->{"\U$_"}; --- a/lib/ModPerl/MM.pm +++ a/lib/ModPerl/MM.pm @@ -69,10 +69,12 @@ sub add_dep_after { $$string =~ s/($targ\s+::.*?$after_targ)/$1 $add/; } +my $build; + sub build_config { my $key = shift; require Apache2::Build; - my $build = Apache2::Build->build_config; + $build ||= Apache2::Build->build_config; return $build unless $key; $build->{$key}; } @@ -97,15 +99,14 @@ sub my_import { my @default_opts = qw(CCFLAGS LIBS INC OPTIMIZE LDDLFLAGS TYPEMAPS); my @default_dlib_opts = qw(OTHERLDFLAGS); my @default_macro_opts = (); -my $b = build_config(); my %opts = ( - CCFLAGS => sub { $b->{MODPERL_CCOPTS} }, - LIBS => sub { join ' ', $b->apache_libs, $b->modperl_libs }, - INC => sub { $b->inc; }, - OPTIMIZE => sub { $b->perl_config('optimize'); }, - LDDLFLAGS => sub { $b->perl_config('lddlflags'); }, - TYPEMAPS => sub { $b->typemaps; }, - OTHERLDFLAGS => sub { $b->otherldflags; }, + CCFLAGS => sub { $build->{MODPERL_CCOPTS} }, + LIBS => sub { join ' ', $build->apache_libs, $build->modperl_libs }, + INC => sub { $build->inc; }, + OPTIMIZE => sub { $build->perl_config('optimize'); }, + LDDLFLAGS => sub { $build->perl_config('lddlflags'); }, + TYPEMAPS => sub { $build->typemaps; }, + OTHERLDFLAGS => sub { $build->otherldflags; }, ); sub get_def_opt { @@ -128,7 +129,7 @@ sub WriteMakefile { $eu_mm_mv_all_methods_overriden++; } - my $build = build_config(); + $build ||= build_config(); my_import(__PACKAGE__); # set top-level WriteMakefile's values if weren't set already @@ -158,7 +159,7 @@ sub WriteMakefile { sub ModPerl::MM::MY::post_initialize { my $self = shift; - my $build = build_config(); + $build ||= build_config(); my $pm = $self->{PM}; while (my ($k, $v) = each %PM) { --- a/lib/ModPerl/WrapXS.pm +++ a/lib/ModPerl/WrapXS.pm @@ -155,9 +155,16 @@ EOF my $retval = $return_type eq 'void' ? ["", ""] : ["RETVAL = ", "OUTPUT:\n RETVAL\n"]; - + + my $avoid_warning = ""; + if (@$args and not $passthru) { + $avoid_warning = " /* avoiding -Wall warnings */\n"; + $avoid_warning .= join "\n", + (map " $_->{name} = $_->{name};", @$args), ""; + } $code .= <[0]$dispatch($thx$parms); $retval->[1] --- a/lib/mod_perl2.pm +++ a/lib/mod_perl2.pm @@ -19,7 +19,7 @@ use 5.006; use strict; BEGIN { - our $VERSION = "2.000005"; + our $VERSION = "2.000006"; our $VERSION_TRIPLET; if ($VERSION =~ /(\d+)\.(\d\d\d)(\d+)/) { --- a/src/modules/perl/mod_perl.c +++ a/src/modules/perl/mod_perl.c @@ -439,13 +439,13 @@ int modperl_init_vhost(server_rec *s, apr_pool_t *p, void modperl_init(server_rec *base_server, apr_pool_t *p) { server_rec *s; - modperl_config_srv_t *base_scfg; PerlInterpreter *base_perl; - - base_scfg = modperl_config_srv_get(base_server); +#ifdef MP_TRACE + modperl_config_srv_t *base_scfg = modperl_config_srv_get(base_server); MP_TRACE_d_do(MpSrv_dump_flags(base_scfg, base_server->server_hostname)); +#endif /* MP_TRACE */ #ifndef USE_ITHREADS if (modperl_threaded_mpm()) { --- a/src/modules/perl/modperl_const.c +++ a/src/modules/perl/modperl_const.c @@ -51,7 +51,7 @@ static void new_constsub(pTHX_ constants_lookup lookup, gv_init(alias, caller_stash, name, name_len, TRUE); } - GvCV_set(alias, GvCV(*gvp)); + GvCV_set(alias, MUTABLE_CV(SvREFCNT_inc(GvCV(*gvp)))); } } --- a/src/modules/perl/modperl_error.c +++ a/src/modules/perl/modperl_error.c @@ -78,7 +78,7 @@ void modperl_croak(pTHX_ apr_status_t rc, const char* func) } if (SvTRUE(ERRSV)) { - Perl_croak(aTHX_ "%s", SvPV_nolen(ERRSV)); + Perl_croak(aTHX_ Nullch); } stash = gv_stashpvn("APR::Error", 10, FALSE); --- a/src/modules/perl/modperl_error.h +++ a/src/modules/perl/modperl_error.h @@ -45,4 +45,20 @@ void modperl_croak(pTHX_ apr_status_t rc, const char* func); } \ } STMT_END +#define MP_RUN_CROAK_RESET_OK(s, rc_run, func) STMT_START \ + { \ + apr_status_t rc = rc_run; \ + if (rc != APR_SUCCESS) { \ + if (APR_STATUS_IS_ECONNRESET(rc) || \ + APR_STATUS_IS_ECONNABORTED(rc)) { \ + ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, \ + "%s got: %s", func, \ + modperl_error_strerror(aTHX_ rc)); \ + } \ + else { \ + modperl_croak(aTHX_ rc, func); \ + } \ + } \ + } STMT_END + #endif /* MODPERL_ERROR_H */ --- a/src/modules/perl/modperl_filter.c +++ a/src/modules/perl/modperl_filter.c @@ -472,24 +472,6 @@ static int modperl_run_filter_init(ap_filter_t *f, return status; } - -#define MP_RUN_CROAK_RESET_OK(func) \ - { \ - apr_status_t rc = func(filter); \ - if (rc != APR_SUCCESS) { \ - if (APR_STATUS_IS_ECONNRESET(rc) || \ - APR_STATUS_IS_ECONNABORTED(rc)) { \ - ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, \ - "Apache2::Filter internal flush got: %s", \ - modperl_error_strerror(aTHX_ rc)); \ - } \ - else { \ - modperl_croak(aTHX_ rc, \ - "Apache2::Filter internal flush"); \ - } \ - } \ - } - int modperl_run_filter(modperl_filter_t *filter) { AV *args = Nullav; @@ -563,10 +545,12 @@ int modperl_run_filter(modperl_filter_t *filter) apr_brigade_destroy(filter->bb_in); filter->bb_in = NULL; } - MP_RUN_CROAK_RESET_OK(modperl_input_filter_flush); + MP_RUN_CROAK_RESET_OK(s, modperl_input_filter_flush(filter), + "Apache2::Filter internal flush"); } else { - MP_RUN_CROAK_RESET_OK(modperl_output_filter_flush); + MP_RUN_CROAK_RESET_OK(s, modperl_output_filter_flush(filter), + "Apache2::Filter internal flush"); } MP_FILTER_RESTORE_ERRSV(errsv); --- a/src/modules/perl/modperl_io_apache.c +++ a/src/modules/perl/modperl_io_apache.c @@ -169,8 +169,9 @@ PerlIOApache_flush(pTHX_ PerlIO *f) rcfg->wbucket->outbuf, rcfg->wbucket->outcnt)); - MP_RUN_CROAK(modperl_wbucket_flush(rcfg->wbucket, FALSE), - ":Apache2 IO flush"); + MP_RUN_CROAK_RESET_OK(st->r->server, + modperl_wbucket_flush(rcfg->wbucket, FALSE), + ":Apache2 IO flush"); return 0; } --- a/src/modules/perl/modperl_module.c +++ a/src/modules/perl/modperl_module.c @@ -297,8 +297,8 @@ modperl_module_config_create_obj(pTHX_ } MP_TRACE_c(MP_FUNC, "%s cfg=0x%lx for %s.%s", - method, (unsigned long)cfg, - mname, parms->cmd->name); + method ? modperl_mgv_last_name(method) : "NULL", + (unsigned long)cfg, mname, parms->cmd->name); /* used by merge functions to get a Perl interp */ cfg->server = parms->server; @@ -741,8 +741,6 @@ static const char *modperl_module_add_cmds(apr_pool_t *p, server_rec *s, static void modperl_module_insert(module *modp) { - module *m; - /* * insert after mod_perl, rather the top of the list. * (see ap_add_module; does not insert into ap_top_module list if @@ -750,14 +748,8 @@ static void modperl_module_insert(module *modp) * this way, modperl config merging happens before this module. */ - for (m = ap_top_module; m; m=m->next) { - if (m == &perl_module) { - module *next = m->next; - m->next = modp; - modp->next = next; - break; - } - } + modp->next = perl_module.next; + perl_module.next = modp; } #define MP_isGV(gv) (gv && isGV(gv)) --- a/src/modules/perl/modperl_pcw.c +++ a/src/modules/perl/modperl_pcw.c @@ -27,7 +27,11 @@ void ap_pcw_walk_location_config(apr_pool_t *pconf, server_rec *s, ap_pcw_dir_cb_t dir_cb, void *data) { int i; - ap_conf_vector_t **urls = (ap_conf_vector_t **)sconf->sec_url->elts; + ap_conf_vector_t **urls; + + if( !sconf->sec_url ) return; + + urls = (ap_conf_vector_t **)sconf->sec_url->elts; for (i = 0; i < sconf->sec_url->nelts; i++) { core_dir_config *conf = @@ -46,7 +50,11 @@ void ap_pcw_walk_directory_config(apr_pool_t *pconf, server_rec *s, ap_pcw_dir_cb_t dir_cb, void *data) { int i; - ap_conf_vector_t **dirs = (ap_conf_vector_t **)sconf->sec_dir->elts; + ap_conf_vector_t **dirs; + + if( !sconf->sec_dir ) return; + + dirs = (ap_conf_vector_t **)sconf->sec_dir->elts; for (i = 0; i < sconf->sec_dir->nelts; i++) { core_dir_config *conf = @@ -65,7 +73,11 @@ void ap_pcw_walk_files_config(apr_pool_t *pconf, server_rec *s, ap_pcw_dir_cb_t dir_cb, void *data) { int i; - ap_conf_vector_t **dirs = (ap_conf_vector_t **)dconf->sec_file->elts; + ap_conf_vector_t **dirs; + + if( !dconf->sec_file ) return; + + dirs = (ap_conf_vector_t **)dconf->sec_file->elts; for (i = 0; i < dconf->sec_file->nelts; i++) { core_dir_config *conf = --- a/src/modules/perl/modperl_perl.c +++ a/src/modules/perl/modperl_perl.c @@ -55,7 +55,8 @@ void modperl_perl_core_global_init(pTHX) while (cglobals->name) { GV *gv = gv_fetchpv(cglobals->core_name, TRUE, SVt_PVCV); - GvCV_set(gv, get_cv(cglobals->sub_name, TRUE)); + GvCV_set(gv, + MUTABLE_CV(SvREFCNT_inc(get_cv(cglobals->sub_name, TRUE)))); GvIMPORTED_CV_on(gv); cglobals++; } --- a/src/modules/perl/modperl_perl_global.c +++ a/src/modules/perl/modperl_perl_global.c @@ -338,6 +338,9 @@ modperl_perl_global_gvhv_restore(pTHX_ modperl_perl_global_gvhv_t *gvhv) */ MP_magical_untie(gvhv->tmphv, mg_flags); SvREFCNT_dec(gvhv->tmphv); + + /* avoiding -Wall warning */ + mg_flags = mg_flags; } static void --- a/src/modules/perl/modperl_svptr_table.c +++ a/src/modules/perl/modperl_svptr_table.c @@ -30,7 +30,7 @@ #ifdef USE_ITHREADS #if MP_PERL_BRANCH(5, 6) -# define my_sv_dup(s, p) sv_dup(s) +# define my_sv_dup(s, p) SvREFCNT_inc(sv_dup(s)) typedef struct { AV *stashes; @@ -39,7 +39,11 @@ typedef struct { } CLONE_PARAMS; #else -# define my_sv_dup(s, p) sv_dup(s, p) +# ifdef sv_dup_inc +# define my_sv_dup(s, p) sv_dup_inc(s, p) +# else +# define my_sv_dup(s, p) SvREFCNT_inc(sv_dup(s, p)) +# endif #endif /* @@ -89,8 +93,7 @@ PTR_TBL_t *modperl_svptr_table_clone(pTHX_ PerlInterpreter *proto_perl, /* key is just a pointer we do not modify, no need to copy */ dst_ent->oldval = src_ent->oldval; - dst_ent->newval = - SvREFCNT_inc(my_sv_dup((SV*)src_ent->newval, &parms)); + dst_ent->newval = my_sv_dup((SV*)src_ent->newval, &parms); } } --- a/src/modules/perl/modperl_tipool.c +++ a/src/modules/perl/modperl_tipool.c @@ -328,9 +328,9 @@ static void modperl_tipool_putback_base(modperl_tipool_t *tipool, MP_TRACE_i(MP_FUNC, "0x%lx now available (%d in use, %d running)", (unsigned long)listp->data, tipool->in_use, tipool->size); + modperl_tipool_broadcast(tipool); if (tipool->in_use == (tipool->cfg->max - 1)) { /* hurry up, another thread may be blocking */ - modperl_tipool_broadcast(tipool); modperl_tipool_unlock(tipool); return; } --- a/t/api/err_headers_out.t +++ a/t/api/err_headers_out.t @@ -19,6 +19,14 @@ my $location = '/TestAPI__err_headers_out'; ok t_cmp $res->code, 200, "OK"; + # HTTP::Headers 6.00 makes the next 2 tests fail. When the response comes + # in the header name is stored as "x-err_headers_out". But when it is to + # be read below it is referred as "x-err-headers-out" and hence not found. + local $HTTP::Headers::TRANSLATE_UNDERSCORE= + $HTTP::Headers::TRANSLATE_UNDERSCORE; + undef $HTTP::Headers::TRANSLATE_UNDERSCORE + if defined HTTP::Headers->VERSION and HTTP::Headers->VERSION==6.00; + ok t_cmp $res->header('X-err_headers_out'), "err_headers_out", "X-err_headers_out: made it"; @@ -36,6 +44,14 @@ my $location = '/TestAPI__err_headers_out'; ok t_cmp $res->code, 404, "not found"; + # HTTP::Headers 6.00 makes this test fail. When the response comes in + # the header name is stored as "x-err_headers_out". But when it is to + # be read below it is referred as "x-err-headers-out" and hence not found. + local $HTTP::Headers::TRANSLATE_UNDERSCORE= + $HTTP::Headers::TRANSLATE_UNDERSCORE; + undef $HTTP::Headers::TRANSLATE_UNDERSCORE + if defined HTTP::Headers->VERSION and HTTP::Headers->VERSION==6.00; + ok t_cmp $res->header('X-err_headers_out'), "err_headers_out", "X-err_headers_out: made it"; --- a/t/conf/extra.conf.in +++ a/t/conf/extra.conf.in @@ -73,6 +73,10 @@ PerlModule TestExit::FromPerlModule SetEnv TMPDIR @t_logs@ + + # pass ld_library_path for non standard lib locations + # [rt.cpan.org #66085] + PassEnv LD_LIBRARY_PATH # --- a/t/conf/post_config_startup.pl +++ a/t/conf/post_config_startup.pl @@ -98,20 +98,29 @@ sub test_perl_ithreads { } sub test_server_shutdown_cleanup_register { - # we can't really test the functionality since it happens at - # server shutdown, when the test suite has finished its run - # so just check that we can register the cleanup and that it - # doesn't segfault - Apache2::ServerUtil::server_shutdown_cleanup_register(sub { Apache2::Const::OK }); - - # replace the sub with the following to get some visual debug - # should log cnt:1 on -start, oncand cnt: 2 -stop followed by cnt: 1) - #Apache2::ServerUtil::server_shutdown_cleanup_register( sub { - # my $cnt = Apache2::ServerUtil::restart_count(); - # open my $fh, ">>/tmp/out" or die "$!"; - # print $fh "cnt: $cnt\n"; - # close $fh; - #}); + Apache2::ServerUtil::server_shutdown_cleanup_register sub { + warn <<'EOF'; +*** done with server_shutdown_cleanup_register *** +******************************************************************************** +EOF + }; + + Apache2::ServerUtil::server_shutdown_cleanup_register sub { + die "testing server_shutdown_cleanup_register\n"; + }; + + Apache2::ServerUtil::server_shutdown_cleanup_register sub { + warn <<'EOF'; +******************************************************************************** +*** This is a test for Apache2::ServerUtil::server_shutdown_cleanup_register *** +*** Following a line consisting only of * characters there should be a line *** +*** containing *** +*** "cleanup died: testing server_shutdown_cleanup_register". *** +*** The next line should then read *** +*** "done with server_shutdown_cleanup_register" *** +******************************************************************************** +EOF + }; } sub ModPerl::Test::exit_handler { --- a/t/filter/TestFilter/out_str_reverse.pm +++ a/t/filter/TestFilter/out_str_reverse.pm @@ -16,12 +16,21 @@ use TestCommon::Utils (); use Apache2::Const -compile => qw(OK M_POST); use constant BUFF_LEN => 2; +use constant signature => "Reversed by mod_perl 2.0\n"; sub handler { my $f = shift; #warn "called\n"; my $leftover = $f->ctx; + + # We are about to change the length of the response body. Hence, we + # have to adjust the content-length header. + unless (defined $leftover) { # 1st invocation + $f->r->headers_out->{'Content-Length'}+=length signature + if exists $f->r->headers_out->{'Content-Length'}; + } + while ($f->read(my $buffer, BUFF_LEN)) { #warn "buffer: [$buffer]\n"; $buffer = $leftover . $buffer if defined $leftover; @@ -34,7 +43,7 @@ sub handler { if ($f->seen_eos) { $f->print(scalar reverse $leftover) if defined $leftover; - $f->print("Reversed by mod_perl 2.0\n"); + $f->print(signature); } else { $f->ctx($leftover) if defined $leftover; --- a/t/lib/TestAPRlib/pool.pm +++ a/t/lib/TestAPRlib/pool.pm @@ -11,7 +11,7 @@ use APR::Pool (); use APR::Table (); sub num_of_tests { - return 75; + return 77; } sub test { @@ -333,21 +333,44 @@ sub test { { my $p = APR::Pool->new; $p->cleanup_register('TestAPR::pool::some_non_existing_sub', 1); - eval { $p->destroy }; - ok t_cmp($@, + + my @warnings; + local $SIG{__WARN__} = sub {push @warnings, @_}; + $p->destroy; + + ok t_cmp($warnings[0], qr/Undefined subroutine/, "non existing function"); } { my $p = APR::Pool->new; $p->cleanup_register(\&non_existing1, 1); - eval { $p->destroy }; - ok t_cmp($@, + + my @warnings; + local $SIG{__WARN__} = sub {push @warnings, @_}; + $p->destroy; + + ok t_cmp($warnings[0], qr/Undefined subroutine/, "non existing function"); } - + # cleanups throwing exceptions + { + my $p = APR::Pool->new; + $p->cleanup_register(sub {die "1\n"}, 1); + $p->cleanup_register(sub {die "2\n"}, 1); + + my @warnings; + local $SIG{__WARN__} = sub {push @warnings, @_}; + local $@="to be preserved"; + undef $p; + + ok t_cmp(\@warnings, + [map "APR::Pool: cleanup died: $_\n", 2, 1], + "exceptions thrown by cleanups"); + ok t_cmp($@, "to be preserved", '$@ is preserved'); + } ### $p->clear ### { --- a/t/protocol/TestProtocol/pseudo_http.pm +++ a/t/protocol/TestProtocol/pseudo_http.pm @@ -165,6 +165,8 @@ __END__ AuthUserFile @ServerRoot@/htdocs/protocols/basic-auth + AuthName TestProtocol::pseudo_http + AuthType Basic Require user stas Satisfy any --- a/t/response/TestAPI/add_config.pm +++ a/t/response/TestAPI/add_config.pm @@ -121,7 +121,7 @@ __END__ # APACHE_TEST_CONFIG_ORDER 950 - PerlModule TestAPI::add_config + PerlLoadModule TestAPI::add_config AccessFileName htaccess SetHandler modperl --- a/t/response/TestAPI/request_rec.pm +++ a/t/response/TestAPI/request_rec.pm @@ -57,8 +57,9 @@ sub handler { ok $r->protocol =~ /http/i; - # HTTP 1.0 - ok t_cmp $r->proto_num, 1000, 't->proto_num'; + # LWP >=6.00 uses HTTP/1.1, other HTTP/1.0 + ok t_cmp $r->proto_num, 1000+substr($r->the_request, -1), + 't->proto_num'; ok t_cmp lc($r->hostname), lc($r->get_server_name), '$r->hostname'; @@ -124,7 +125,12 @@ sub handler { ok t_cmp $r->args, $args, '$r->args'; - ok t_cmp $r->the_request, "GET $base_uri$path_info?$args HTTP/1.0", + # LWP uses HTTP/1.1 since 6.00 + ok t_cmp $r->the_request, qr!GET + \x20 + \Q$base_uri$path_info\E\?\Q$args\E + \x20 + HTTP/1\.\d!x, '$r->the_request'; { --- a/t/response/TestAPI/server_const.pm +++ a/t/response/TestAPI/server_const.pm @@ -24,7 +24,7 @@ sub handler { my $r = shift; - plan $r, tests => 5; + plan $r, tests => 6; # test Apache2::ServerUtil constant subroutines @@ -36,20 +36,22 @@ sub handler { $built, 'Apache2::ServerUtil::get_server_built()'); - ok t_cmp(Apache2::ServerUtil::get_server_description, - $version, + my $server_descr = Apache2::ServerUtil::get_server_description; + ok t_cmp($server_descr, qr/^\Q$version\E/, 'Apache2::ServerUtil::get_server_description()'); - my $server_version = Apache2::ServerUtil::get_server_version; - ok t_cmp($version, - qr/^$server_version/, - 'Apache2::ServerUtil::get_server_version()'); + # added via $s->add_version_component in t/conf/modperl_extra.pl + ok t_cmp($server_descr, qr!\bworld domination series/2\.0\b!, + 'Apache2::ServerUtil::get_server_description() -- component'); - my $server_banner = Apache2::ServerUtil::get_server_banner; - ok t_cmp($version, - qr/^$server_banner/, + # assuming ServerTokens Full (default) the banner equals description + ok t_cmp(Apache2::ServerUtil::get_server_banner, $server_descr, 'Apache2::ServerUtil::get_server_banner()'); + # version is just an alias for banner + ok t_cmp(Apache2::ServerUtil::get_server_version, $server_descr, + 'Apache2::ServerUtil::get_server_version()'); + Apache2::Const::OK; } --- a/todo/2.0.5 +++ a/todo/2.0.5 @@ -1,10 +0,0 @@ -SHOW STOPPERS -==================== -- Windows Segfaults [needs windows developer owner, ] -- MANIFEST verifications [needs detail, ] -- rt.cpan.org PRs [pgollucci, phred, ] - -NICE TO HAVE -============= -- Smolder, https://issues.apache.org/jira/browse/INFRA-1612 [pgollucci, ] - --- a/todo/2.0.6 +++ a/todo/2.0.6 @@ -0,0 +1,10 @@ +SHOW STOPPERS +==================== +- Windows Segfaults [needs windows developer owner, ] +- MANIFEST verifications [needs detail, ] +- rt.cpan.org PRs [pgollucci, phred, ] + +NICE TO HAVE +============= +- Smolder, https://issues.apache.org/jira/browse/INFRA-1612 [pgollucci, ] + --- a/xs/APR/Pool/APR__Pool.h +++ a/xs/APR/Pool/APR__Pool.h @@ -285,6 +285,7 @@ static apr_status_t mpxs_cleanup_run(void *data) } PUTBACK; + save_gp(PL_errgv, 1); /* local *@ */ count = call_sv(cdata->cv, G_SCALAR|G_EVAL); SPAGAIN; @@ -293,6 +294,11 @@ static apr_status_t mpxs_cleanup_run(void *data) (void)POPs; /* the return value is ignored */ } + if (SvTRUE(ERRSV)) { + Perl_warn(aTHX_ "APR::Pool: cleanup died: %s", + SvPV_nolen(ERRSV)); + } + PUTBACK; FREETMPS;LEAVE; @@ -311,10 +317,6 @@ static apr_status_t mpxs_cleanup_run(void *data) } #endif - if (SvTRUE(ERRSV)) { - Perl_croak(aTHX_ SvPV_nolen(ERRSV)); - } - /* the return value is ignored by apr_pool_destroy anyway */ return APR_SUCCESS; } --- a/xs/Apache2/RequestIO/Apache2__RequestIO.h +++ a/xs/Apache2/RequestIO/Apache2__RequestIO.h @@ -179,8 +179,9 @@ void mpxs_Apache2__RequestRec_rflush(pTHX_ I32 items, rcfg->wbucket->outcnt, apr_pstrmemdup(rcfg->wbucket->pool, rcfg->wbucket->outbuf, rcfg->wbucket->outcnt)); - MP_RUN_CROAK(modperl_wbucket_flush(rcfg->wbucket, TRUE), - "Apache2::RequestIO::rflush"); + MP_RUN_CROAK_RESET_OK(r->server, + modperl_wbucket_flush(rcfg->wbucket, TRUE), + "Apache2::RequestIO::rflush"); } static MP_INLINE long mpxs_ap_get_client_block(pTHX_ request_rec *r, --- a/xs/Apache2/RequestUtil/Apache2__RequestUtil.h +++ a/xs/Apache2/RequestUtil/Apache2__RequestUtil.h @@ -154,12 +154,6 @@ int mpxs_Apache2__RequestRec_location_merge(request_rec *r, &core_module); if (strEQ(entry->d, location)) { - if (!entry->ap_auth_type) { - entry->ap_auth_type = "Basic"; - } - if (!entry->ap_auth_name) { - entry->ap_auth_name = apr_pstrdup(p, location); - } r->per_dir_config = ap_merge_per_dir_configs(p, s->lookup_defaults, sec[i]); return 1; --- a/xs/Apache2/ServerUtil/Apache2__ServerUtil.h +++ a/xs/Apache2/ServerUtil/Apache2__ServerUtil.h @@ -53,6 +53,7 @@ static apr_status_t mpxs_cleanup_run(void *data) mpxs_cleanup2_t *cdata = (mpxs_cleanup2_t *)data; #ifdef USE_ITHREADS dTHXa(cdata->perl); + PERL_SET_CONTEXT(aTHX); #endif dSP; @@ -63,6 +64,7 @@ static apr_status_t mpxs_cleanup_run(void *data) } PUTBACK; + save_gp(PL_errgv, 1); /* local *@ */ count = call_sv(cdata->cv, G_SCALAR|G_EVAL); SPAGAIN; @@ -71,6 +73,11 @@ static apr_status_t mpxs_cleanup_run(void *data) (void)POPs; /* the return value is ignored */ } + if (SvTRUE(ERRSV)) { + Perl_warn(aTHX_ "Apache2::ServerUtil: cleanup died: %s", + SvPV_nolen(ERRSV)); + } + PUTBACK; FREETMPS;LEAVE; @@ -79,10 +86,6 @@ static apr_status_t mpxs_cleanup_run(void *data) SvREFCNT_dec(cdata->arg); } - if (SvTRUE(ERRSV)) { - Perl_croak(aTHX_ SvPV_nolen(ERRSV)); - } - /* the return value is ignored by apr_pool_destroy anyway */ return APR_SUCCESS; } @@ -185,6 +188,13 @@ void mpxs_Apache2__ServerRec_add_config(pTHX_ server_rec *s, SV *lines) } } +#define mpxs_Apache2__ServerRec_get_server_banner \ + ap_get_server_banner() +#define mpxs_Apache2__ServerRec_get_server_description \ + ap_get_server_description() +#define mpxs_Apache2__ServerRec_get_server_version \ + ap_get_server_version() + static void mpxs_Apache2__ServerUtil_BOOT(pTHX) { newCONSTSUB(PL_defstash, "Apache2::ServerUtil::server_root", @@ -192,13 +202,4 @@ static void mpxs_Apache2__ServerUtil_BOOT(pTHX) newCONSTSUB(PL_defstash, "Apache2::ServerUtil::get_server_built", newSVpv(ap_get_server_built(), 0)); - - newCONSTSUB(PL_defstash, "Apache2::ServerUtil::get_server_version", - newSVpv(ap_get_server_version(), 0)); - - newCONSTSUB(PL_defstash, "Apache2::ServerUtil::get_server_banner", - newSVpv(ap_get_server_banner(), 0)); - - newCONSTSUB(PL_defstash, "Apache2::ServerUtil::get_server_description", - newSVpv(ap_get_server_description(), 0)); } --- a/xs/Apache2/SubProcess/Apache2__SubProcess.h +++ a/xs/Apache2/SubProcess/Apache2__SubProcess.h @@ -135,7 +135,7 @@ MP_STATIC XS(MPXS_modperl_spawn_proc_prog) const char *usage = "Usage: spawn_proc_prog($r, $command, [\\@argv])"; if (items < 2) { - Perl_croak(aTHX_ usage); + Perl_croak(aTHX_ "%s", usage); } SP -= items; @@ -156,7 +156,7 @@ MP_STATIC XS(MPXS_modperl_spawn_proc_prog) av_items = len+1; } else { - Perl_croak(aTHX_ usage); + Perl_croak(aTHX_ "%s", usage); } } --- a/xs/maps/apache2_functions.map +++ a/xs/maps/apache2_functions.map @@ -165,6 +165,9 @@ MODULE=Apache2::ServerUtil PACKAGE=Apache2::ServerRec BOOT=1 MODULE=Apache2::ServerUtil PACKAGE=Apache2::ServerUtil ap_exists_config_define ap_server_root_relative | | p, fname="" + ap_get_server_banner + ap_get_server_description + ap_get_server_version MODULE=Apache2::ServerUtil PACKAGE=guess ap_error_log2stderr @@ -175,9 +178,6 @@ MODULE=Apache2::ServerUtil PACKAGE=guess #however it is not exported on win32 !ap_get_local_host ~ap_get_server_built -~ap_get_server_version -~ap_get_server_banner -~ap_get_server_description ~ap_server_root