Package: libapache2-mod-perl2
Version: 2.0.10-2
Severity: important
Tags: patch upstream
-- Package-specific info:
-8<-- Start Bug Report 8<--
1. Problem Description:
To reproduce the problem, start from a vanilla Debian server (I used 9.5).
Install apache2, libapache2-mod-perl2, libev-perl
Create 2 perl files with following content:
handler1.pl:
#!/usr/bin/perl
my $pwd = `/bin/pwd`;
1;
handler2.pl:
#!/usr/bin/perl
use EV;
my $w = EV::signal 'CHLD', sub {
print "SIGCHLD received\n";
};
1;
Reference them in two PerlRequire directive, either in
/etc/apache2/apache2.conf or in a separate conf file in
/etc/apache2/conf-enabled:
# order is important
PerlRequire "/path/to/handler1.pl"
PerlRequire "/path/to/handler2.pl"
Apache will crash on startup.
===
I did an in-depth analysis of this bug. What happens is the following:
The backtick operator in handler1.pl internally calls waitpid, which
internally waits for the SIGCHLD signal.
EV::signal 'CHLD' installs a signal handler using sigaction (see
libev-perl-4.22: libev/ev.c::ev_signal_start). There is no provision to remove
this signal handler. The handler is located in EV.so, loaded by the XS loader.
apache2 goes through 3 stages on startup: pre-config, destroy-config,
create-config
In the pre-config stage, the 2 PerlRequire commands are executed and the
signal handler is installed at process level.
In the destroy-config stage, all modules are removed, including mod_perl,
which consists in removing all XS modules (see libapache2-mod-perl2-2.0.10:
src/modules/perl/modperl_interp.c::modperl_interp_destroy())
At this point the signal handler is still registered at process level but
points to invalid memory!
In the create-config stage, the config is recreated, handler1.pl is reloaded
and the backtick operator triggers a SIGCHLD, which causes a SIGEV because the
signal handler is not in memory (the EV.so library will only be loaded when the
second PerlRequire is executed).
I came to the conclusion that unloading the XS modules when mod_perl is
unloaded is very harsh; the perl interpretor is clearly not designed for that.
I tested a patch where the unloading of XS modules is simply skipped. It's
working and it also fixes another bug that I will report separately:
--- a/src/modules/perl/modperl_interp.c 2018-08-03 20:49:54.0 +0200
+++ b/src/modules/perl/modperl_interp.c 2018-08-03 20:49:54.0 +0200
@@ -122,11 +122,11 @@
MP_TRACE_i(MP_FUNC, "*error - still in use!*");
}
-handles = modperl_xs_dl_handles_get(aTHX);
+/*handles = modperl_xs_dl_handles_get(aTHX);*/
modperl_perl_destruct(interp->perl);
-modperl_xs_dl_handles_close(handles);
+/*modperl_xs_dl_handles_close(handles);*/
free(interp);
}
2. Used Components and their Configuration:
*** mod_perl version 2.10
*** using /usr/lib/x86_64-linux-gnu/perl5/5.24/Apache2/BuildConfig.pm
*** Makefile.PL options:
MP_APR_CONFIG => /usr/bin/apr-config
MP_APR_LIB => aprext
MP_APXS=> /usr/bin/apxs
MP_CCOPTS => -g -O2
-fdebug-prefix-map=/build/libapache2-mod-perl2-go9ZTa/libapache2-mod-perl2-2.0.10=.
-fstack-protector-strong -Wformat -Werror=format-security -Wall -fgnu89-inline
MP_COMPAT_1X => 1
MP_GENERATE_XS => 1
MP_LIBNAME => mod_perl
MP_TRACE => 0
MP_USE_DSO => 1
MP_USE_STATIC => 0
*** The httpd binary was not found
*** (apr|apu)-config linking info
-L/usr/lib/x86_64-linux-gnu -laprutil-1
-L/usr/lib/x86_64-linux-gnu -lapr-1
*** /usr/bin/perl -V
Summary of my perl5 (revision 5 version 24 subversion 1) configuration:
Platform:
osname=linux, osvers=3.16.0, archname=x86_64-linux-gnu-thread-multi
uname='linux localhost 3.16.0 #1 smp debian 3.16.0 x86_64 gnulinux '
config_args='-Dusethreads -Duselargefiles -Dcc=x86_64-linux-gnu-gcc
-Dcpp=x86_64-linux-gnu-cpp -Dld=x86_64-linux-gnu-gcc -Dccflags=-DDEBIAN
-Wdate-time -D_FORTIFY_SOURCE=2 -g -O2
-fdebug-prefix-map=/build/perl-N8J5tr/perl-5.24.1=. -fstack-protector-strong
-Wformat -Werror=format-security -Dldflags= -Wl,-z,relro -Dlddlflags=-shared
-Wl,-z,relro -Dcccdlflags=-fPIC -Darchname=x86_64-linux-gnu -Dprefix=/usr
-Dprivlib=/usr/share/perl/5.24 -Darchlib=/usr/lib/x86_64-linux-gnu/perl/5.24
-Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5
-Dvendorarch=/usr/lib/x86_64-linux-gnu/perl5/5.24 -Dsiteprefix=/usr/local
-Dsitelib=/usr/local/share/perl/5.24.1
-Dsitearch=/usr/local/lib/x86_64-linux-gnu/perl/5.24.1
-Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3
-Dsiteman1dir=/usr/local/man/man1 -Dsiteman3dir=/usr/local/man/man3
-Dusesitecustomize -Duse64bitint -Dman1ext=1 -Dman3ext=3perl
-Dpager=/usr/bin/sensible-pager -Uafs -Ud_csh -Ud_ualarm -Uusesfio -Uusenm
-Ui