You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Benoit Bolsee <be...@online.be> on 2018/08/16 10:50:46 UTC

[mp2] crash when using EV::signal 'CHLD' and backtick operator at the same time

-------------8<---------- Start Bug Report ------------8<----------
1. Problem Description:

  To reproduce the problem, start from Debian vanilla server (I used
testing (buster)).
  Install apache2, libapache2-mod-perl2, libev-perl
  (I also used development version of perl, mod_perl and EV with the
same result)
  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. Here is what happens:

  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
EV-4.22.0: 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 mod_perl:
src/modules/perl/modperl_interp.c::modperl_interp_destroy())
  The removal of EV.so does not restore the signal handler as there is
no cleanup in EV.so.
  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).

  Conclusion:
  Unloading the XS modules relies on the modules to cleanup the global
state properly but it's clearly not the case of the EV module.
  I tested a fix that consists in skipping the unloading of the XS
modules. While it works for my case, it is not a proper solution either
as there are circumstances where it would cause other bugs.
  Ideally the EV module should register a cleanup function to restore
the signal handlers on unload.
  There are similar potential issues when an XS module register some op
checker in PL_check static array: unloading the XS module does not
remove the handler because Perl does not provide an API to do it.
Hopefully, in this case unloading mod_perl will normally causes
libperl to unload as well, which cleans the PL_check array.

  Clearly, Perl is not designed to be unloaded-reloaded. 


2. Used Components and their Configuration:

*** mod_perl version 2.000011

*** using /home/ben/src/mod_perl-2.0/lib/Apache2/BuildConfig.pm

*** Makefile.PL options:
  MP_APR_LIB     => aprext
  MP_APXS        => /usr/bin/apxs
  MP_COMPAT_1X   => 1
  MP_GENERATE_XS => 1
  MP_LIBNAME     => mod_perl
  MP_USE_DSO     => 1


*** /usr/sbin/apache2 -V
Server version: Apache/2.4.34 (Debian)
Server built:   2018-07-27T19:37:37
Server's Module Magic Number: 20120211:79
Server loaded:  APR 1.6.3, APR-UTIL 1.6.1
Compiled using: APR 1.6.3, APR-UTIL 1.6.1
Architecture:   64-bit
Server MPM:     event
  threaded:     yes (fixed thread count)
    forked:     yes (variable process count)
Server compiled with....
 -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 DYNAMIC_MODULE_LIMIT=256
 -D HTTPD_ROOT="/etc/apache2"
 -D SUEXEC_BIN="/usr/lib/apache2/suexec"
 -D DEFAULT_PIDLOG="/var/run/apache2.pid"
 -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
 -D DEFAULT_ERRORLOG="logs/error_log"
 -D AP_TYPES_CONFIG_FILE="mime.types"
 -D SERVER_CONFIG_FILE="apache2.conf"

*** /usr/bin/ldd /usr/sbin/apache2
	linux-vdso.so.1 (0x00007ffdc0dfa000)
	libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f9abcf5b000)
	libaprutil-1.so.0 => /lib/x86_64-linux-gnu/libaprutil-1.so.0
(0x00007f9abcd2f000)
	libapr-1.so.0 => /lib/x86_64-linux-gnu/libapr-1.so.0
(0x00007f9abccf6000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0
(0x00007f9abccd5000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9abcb18000)
	libuuid.so.1 => /lib/x86_64-linux-gnu/libuuid.so.1 (0x00007f9abcb0f000)
	librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f9abcb03000)
	libcrypt.so.1 => /lib/x86_64-linux-gnu/libcrypt.so.1
(0x00007f9abcac9000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f9abcac4000)
	libexpat.so.1 => /lib/x86_64-linux-gnu/libexpat.so.1
(0x00007f9abc892000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f9abd085000)


*** (apr|apu)-config linking info

 -L/usr/lib/x86_64-linux-gnu -laprutil-1    
 -L/usr/lib/x86_64-linux-gnu -lapr-1  



*** /usr/local/bin/perl -V
Summary of my perl5 (revision 5 version 29 subversion 2) configuration:
  Commit id: 48ae8dc39c5996cfd74bb0fefa5026f48ef8445e
  Platform:
    osname=linux
    osvers=4.17.0-1-amd64
    archname=x86_64-linux-thread-multi
    uname='linux testing 4.17.0-1-amd64 #1 smp debian 4.17.8-1
(2018-07-20) x86_64 gnulinux '
    config_args='-es -Dusethreads -A ccflags=-fPIC'
    hint=recommended
    useposix=true
    d_sigaction=define
    useithreads=define
    usemultiplicity=define
    use64bitint=define
    use64bitall=define
    uselongdouble=undef
    usemymalloc=n
    default_inc_excludes_dot=define
    bincompat5005=undef
  Compiler:
    cc='cc'
    ccflags ='-D_REENTRANT -D_GNU_SOURCE -fPIC -fwrapv
-fno-strict-aliasing -pipe -fstack-protector-strong -I/usr/local/include
-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64'
    optimize='-O2'
    cppflags='-D_REENTRANT -D_GNU_SOURCE -fPIC -fwrapv
-fno-strict-aliasing -pipe -fstack-protector-strong
-I/usr/local/include'
    ccversion=''
    gccversion='8.2.0'
    gccosandvers=''
    intsize=4
    longsize=8
    ptrsize=8
    doublesize=8
    byteorder=12345678
    doublekind=3
    d_longlong=define
    longlongsize=8
    d_longdbl=define
    longdblsize=16
    longdblkind=3
    ivtype='long'
    ivsize=8
    nvtype='double'
    nvsize=8
    Off_t='off_t'
    lseeksize=8
    alignbytes=8
    prototype=define
  Linker and Libraries:
    ld='cc'
    ldflags =' -fstack-protector-strong -L/usr/local/lib'

libpth=/usr/local/lib /usr/lib/gcc/x86_64-linux-gnu/8/include-fixed /usr/include/x86_64-linux-gnu /usr/lib /lib/x86_64-linux-gnu /lib/../lib /usr/lib/x86_64-linux-gnu /usr/lib/../lib /lib /lib64 /usr/lib64
    libs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc
    perllibs=-lpthread -lnsl -ldl -lm -lcrypt -lutil -lc
    libc=libc-2.27.so
    so=so
    useshrplib=true
    libperl=libperl.so
    gnulibc_version='2.27'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs
    dlext=so
    d_dlsymun=undef
    ccdlflags='-Wl,-E
-Wl,-rpath,/usr/local/lib/perl5/5.29.2/x86_64-linux-thread-multi/CORE'
    cccdlflags='-fPIC'
    lddlflags='-shared -O2 -L/usr/local/lib -fstack-protector-strong'


Characteristics of this binary (from libperl): 
  Compile-time options:
    HAS_TIMES
    MULTIPLICITY
    PERLIO_LAYERS
    PERL_COPY_ON_WRITE
    PERL_DONT_CREATE_GVSV
    PERL_IMPLICIT_CONTEXT
    PERL_MALLOC_WRAP
    PERL_OP_PARENT
    PERL_PRESERVE_IVUV
    USE_64_BIT_ALL
    USE_64_BIT_INT
    USE_ITHREADS
    USE_LARGE_FILES
    USE_LOCALE
    USE_LOCALE_COLLATE
    USE_LOCALE_CTYPE
    USE_LOCALE_NUMERIC
    USE_LOCALE_TIME
    USE_PERLIO
    USE_PERL_ATOF
    USE_REENTRANT_API
  Built under linux
  Compiled at Aug 14 2018 23:09:13
  %ENV:
    PERL_LWP_USE_HTTP_10="1"
  @INC:
    /usr/local/lib/perl5/site_perl/5.29.2/x86_64-linux-thread-multi
    /usr/local/lib/perl5/site_perl/5.29.2
    /usr/local/lib/perl5/5.29.2/x86_64-linux-thread-multi
    /usr/local/lib/perl5/5.29.2

*** Packages of interest status:

Apache2            : -
Apache2::Request   : -
CGI                : -
ExtUtils::MakeMaker: 7.34
LWP                : -
mod_perl           : -
mod_perl2          : 2.000011


3. This is the core dump trace: (if you get a core dump):


root@testing:/var/log/apache2# gdb /usr/sbin/apache2
GNU gdb (Debian 8.1-4) 8.1
(gdb) run -DONE_PROCESS -DNO_DETACH -k start
Starting program: /usr/sbin/apache2 -DONE_PROCESS -DNO_DETACH -k start
[Thread debugging using libthread_db enabled]
Using host libthread_db library
"/lib/x86_64-linux-gnu/libthread_db.so.1".

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff6fe3d90 in ?? ()
(gdb) bt
#0  0x00007ffff6fe3d90 in ?? ()
#1  <signal handler called>
#2  0x00007ffff7cde214 in __waitpid (pid=15194, stat_loc=0x7fffffffe2c4,
options=0) at ../sysdeps/unix/sysv/linux/waitpid.c:30
#3  0x00007ffff6d68025 in Perl_wait4pid ()
from /usr/local/lib/perl5/5.29.2/x86_64-linux-thread-multi/CORE/libperl.so
#4  0x00007ffff6d6892e in Perl_my_pclose ()
from /usr/local/lib/perl5/5.29.2/x86_64-linux-thread-multi/CORE/libperl.so
#5  0x00007ffff6dd5b06 in Perl_pp_backtick ()
from /usr/local/lib/perl5/5.29.2/x86_64-linux-thread-multi/CORE/libperl.so
#6  0x00007ffff6d84bf6 in Perl_runops_standard ()
from /usr/local/lib/perl5/5.29.2/x86_64-linux-thread-multi/CORE/libperl.so
#7  0x00007ffff6cf9726 in Perl_eval_sv ()
from /usr/local/lib/perl5/5.29.2/x86_64-linux-thread-multi/CORE/libperl.so
#8  0x00007ffff6cf9cf5 in Perl_require_pv ()
from /usr/local/lib/perl5/5.29.2/x86_64-linux-thread-multi/CORE/libperl.so
#9  0x00007ffff779ecce in modperl_require_file ()
from /usr/lib/apache2/modules/mod_perl.so
#10 0x00007ffff7797e4e in modperl_config_apply_PerlRequire ()
from /usr/lib/apache2/modules/mod_perl.so
#11 0x00007ffff77959ac in modperl_startup.localalias ()
from /usr/lib/apache2/modules/mod_perl.so
#12 0x00007ffff77957c3 in modperl_startup.localalias ()
from /usr/lib/apache2/modules/mod_perl.so
#13 0x00007ffff7795c26 in modperl_init ()
from /usr/lib/apache2/modules/mod_perl.so
#14 0x00007ffff7795d96 in modperl_hook_init ()
from /usr/lib/apache2/modules/mod_perl.so
#15 0x00005555555af2b3 in ap_run_open_logs ()
#16 0x000055555558aef2 in main ()



This report was generated by /usr/local/bin/mp2bug on Wed Aug 15
21:27:41 2018 GMT.

-------------8<---------- End Bug Report --------------8<----------