-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 I recently encountered problems with stuck Apache processes that upon analysis can be traced back to the signal handler saving/restoration code within mod_perl. This issue appears to have been originally reported by Charles Jardine in Oct 2002 (see included original e-mail from mod_perl user's list).
The problem stems from the use of Perl's rsignal_state() and rsignal() functions to save and restore, respectively, the SIGALRM signal handler that was installed by Apache. If the OS does not have sigaction() (requiring Perl to use signal() instead), this is fine, as the only arguments to signal() are the signal number and the handler. However, with sigaction(), there are other fields, with the flags being the most important for this particular issue, especially SA_RESTART. Using rsignal_state() and rsignal() does nothing to preserve these other fields; in fact, rsignal() will specifically set SA_RESTART if it is defined (in Perl 5.6.x at least). A better way to handle this for systems with sigaction() is to use the rsignal_save() and rsignal_restore() functions in Perl, which will properly save and restore the sigaction structure, thereby preserving the flags et al. While Perl 5.8.x does not set SA_RESTART (and thereby avoids the specific problem I encountered), saving and restoring the entire sigaction structure seems to me to be "the right thing to do". (For completeness) Red Hat Linux 7.2 Kernel 2.4.20 Apache 1.3.28 mod_perl 1.27 Perl 5.6.1 Doug ######################################################## Index: src/modules/perl/mod_perl.c =================================================================== RCS file: /home/cvspublic/modperl/src/modules/perl/mod_perl.c,v retrieving revision 1.147 diff -u -r1.147 mod_perl.c - --- src/modules/perl/mod_perl.c 2 Oct 2003 21:30:35 -0000 1.147 +++ src/modules/perl/mod_perl.c 18 Dec 2003 16:49:31 -0000 @@ -1124,12 +1124,21 @@ #ifndef WIN32 sigs = (perl_request_sigsave **)cfg->sigsave->elts; for (i=0; i < cfg->sigsave->nelts; i++) { +#ifdef HAS_SIGACTION + MP_TRACE_g(fprintf(stderr, + "mod_perl: restoring SIG%s (%d) handler from: 0x%lx to: 0x%lx\n", + my_signame(sigs[i]->signo), (int)sigs[i]->signo, + (unsigned long)rsignal_state(sigs[i]->signo), + (unsigned long)sigs[i]->h.sa_handler)); + rsignal_restore(sigs[i]->signo, &(sigs[i]->h)); +#else MP_TRACE_g(fprintf(stderr, "mod_perl: restoring SIG%s (%d) handler from: 0x%lx to: 0x%lx\n", my_signame(sigs[i]->signo), (int)sigs[i]->signo, (unsigned long)rsignal_state(sigs[i]->signo), (unsigned long)sigs[i]->h)); rsignal(sigs[i]->signo, sigs[i]->h); +#endif } #endif } Index: src/modules/perl/mod_perl.h =================================================================== RCS file: /home/cvspublic/modperl/src/modules/perl/mod_perl.h,v retrieving revision 1.118 diff -u -r1.118 mod_perl.h - --- src/modules/perl/mod_perl.h 7 Apr 2003 23:16:23 -0000 1.118 +++ src/modules/perl/mod_perl.h 18 Dec 2003 16:49:31 -0000 @@ -1056,7 +1056,7 @@ } perl_dir_config; typedef struct { - - Sighandler_t h; + Sigsave_t h; I32 signo; } perl_request_sigsave; Index: src/modules/perl/perl_config.c =================================================================== RCS file: /home/cvspublic/modperl/src/modules/perl/perl_config.c,v retrieving revision 1.117 diff -u -r1.117 perl_config.c - --- src/modules/perl/perl_config.c 14 Mar 2003 04:55:59 -0000 1.117 +++ src/modules/perl/perl_config.c 18 Dec 2003 16:49:31 -0000 @@ -409,10 +409,18 @@ perl_request_sigsave *sig = (perl_request_sigsave *)pcalloc(p, sizeof(perl_request_sigsave)); sig->signo = whichsig(sigsave[i]); +#ifdef HAS_SIGACTION + rsignal_save(sig->signo, rsignal_state(sig->signo), &(sig->h)); + MP_TRACE_g(fprintf(stderr, + "mod_perl: saving SIG%s (%d) handler 0x%lx\n", + sigsave[i], (int)sig->signo, + (unsigned long)sig->h.sa_handler)); +#else sig->h = rsignal_state(sig->signo); MP_TRACE_g(fprintf(stderr, "mod_perl: saving SIG%s (%d) handler 0x%lx\n", sigsave[i], (int)sig->signo, (unsigned long)sig->h)); +#endif *(perl_request_sigsave **)push_array(cfg->sigsave) = sig; } ######################################################## On 04 October 2002, Charles Jardine wrote: >I have recently seen a number of stuck processes on an >Apache server I run. The problem is associated with events >which appear to be attacks by the Slapper worm. The >server's OpenSSL has been upgraded, so actual penetration >by Slapper does not occur. However the stuck processes >are inconvenient, and threaten DoS. > >I have analysed the problem and discovered that incorrect >manipulation of the handling of alarm signals by mod-perl >is causing some Apache timeouts to fail. > >Software versions: > >Solaris 8 (SPARC 64 bit) >Apache 1.3.26 >perl 5.6.1 >mod-perl 1.26 (source shows same problem in 1.27) >mod-ssl 2.8.10 >OpenSSL 0.9.6e > >The details of the problem are as follows: > >If the processing of a request to the server involves any >perl handlers, mod-perl attempts to save and restore the >Apache's handler for SIGALRM. The handler is saved at line >408 of perl_config.c and restored at line 1122 of mod_perl.c. >(line numbers are from mod-perl version 1.26). > >The save/restore is done using the perl utility functions >rsignal_state and rsignal. > >In perl 5.6.1, rsignal sets the SA_RESTART flag regardless >of the saved state (util.c line 2509). > >The original SIGALRM state is set by Apache by a call >of the libc function signal. This does leaves SA_RESTART clear. > >Thus, the first use of mod-perl in the life of an Apache child >process changes the handling of SIGALRM. Thereafter, some, but >not all, Apache timeouts fail to work. > >Two timeouts which I know to be affected by this are the timeout >associated with the configuration directive KeepAliveTimeout, >and that associated with the mod-ssl warning message >"mod_ssl: SSL handshake timed out". > >Signal handling is greatly changed in perl 5.8. I believe that >this problem will not occur with that version of perl unless >it is compiled with PERL_OLD_SIGNALS. > >I think that it is the code in perl itself which is wrong. >However, I also believe that the problem is serious enough to >warrant a maintenance release of mod-perl which programs round >the broken behaviour of rsignal in the perl versions which are >actually in use at present. > >-- >Charles Jardine - Computing Service, University of Cambridge >[EMAIL PROTECTED] Tel: +44 1223 334506, Fax: +44 1223 334679 -----BEGIN PGP SIGNATURE----- Version: PGPfreeware 7.0.3 for non-commercial use <http://www.pgp.com> iQA/AwUBP+HzcMAaAnPGl8bjEQJOtQCgtSTiroWHvFJpJ5H8N1fqrsjkoUEAoPrC kXkKgApXKeAFFJuqwCCD99CX =BVHX -----END PGP SIGNATURE----- ------------------------------------------------------------ This email, and any included attachments, have been checked by Norton AntiVirus Corporate Edition (Version 8.0), AVG Email Server Edition 7.0, and Merak Email Server Integrated Antivirus (Alwil Software's aVast! engine) and is certified Virus Free. -- Reporting bugs: http://perl.apache.org/bugs/ Mail list info: http://perl.apache.org/maillist/modperl.html