develooper Front page | perl.perl5.porters | Postings from May 2012

[perl #52000] Warn/abort on attempted perl exit

From:
Father Chrysostomos via RT
Date:
May 23, 2012 14:46
Subject:
[perl #52000] Warn/abort on attempted perl exit
Message ID:
rt-3.6.HEAD-7788-1337809578-1947.52000-14-0@perl.org
On Fri Mar 21 15:51:56 2008, jgmyers wrote:
> This is a bug report for perl from jgmyers@pong.us.proofpoint.com,
> generated with the help of perlbug 1.35 running under perl v5.8.8.
> 
> 
> -----------------------------------------------------------------
> [Please enter your report here]

Can someone who understands the exit flags comment on this patch?

> I have a multithreaded C++ server which embeds Perl and has a handful
> of PerlInterpreter objects.  One of the problems is that occasionally
> Perl or some CPAN module will attempt to exit.  In a multithreaded
> process, calling exit() results in bad behavior--the thread will run
> all of the static destructors and atexit handlers and then terminate,
> leaving the remaining threads running, using the already-destructed
> and/or freed static data.  The process will usually dump core some
> time later, possibly after having corrupted persistent data.
> 
> Clearing the PERL_EXIT_EXPECTED bit doesn't quite work right, for
> reasons which I'll mention in a separate bug.  One of the main
> problems with it is that perl unwinds the stack a bit before even
> testing for PERL_EXIT_EXPECTED, so there is no way I can find out
> where in all that perl code the exit came from.
> 
> Below is a patch that adds a PERL_EXIT_WARN feature for embedders.
> This allows one to obtain, through a __WARN__ handler, a perl stack
> trace pointing to the code that attempted to exit.
> 
> Also is a PERL_EXIT_ABORT feature primarily intended to prevent
> infinite recursion through the PERL_EXIT_WARN feature.  It is also
> useful separately to allow a clean abort of the process instead of
> attempting to unwind the stack.
> 
> diff -u perl-5.8.8-1utf8valid/perl.c perl-5.8.8-2xexitwarn/perl.c
> --- perl-5.8.8-1utf8valid/perl.c        2007-06-20 09:46:57.000000000
> -0700
> +++ perl-5.8.8-2xexitwarn/perl.c        2008-03-21 14:32:10.000000000
> -0700
> @@ -5206,6 +5206,15 @@
>  {
>      DEBUG_S(PerlIO_printf(Perl_debug_log, "my_exit: thread %p, status
> %lu\n",
>                           thr, (unsigned long) status));
> +    if (PL_exit_flags & PERL_EXIT_WARN) {
> +       U8 orig_exit_flags = PL_exit_flags;
> +       PL_exit_flags = (PL_exit_flags | PERL_EXIT_ABORT) &
> ~PERL_EXIT_WARN; /* Protect against reentrant calls */
> +       Perl_warn(aTHX_ "Unexpected exit %u", status);
> +       PL_exit_flags = orig_exit_flags;
> +    }
> +    if (PL_exit_flags & PERL_EXIT_ABORT) {
> +       abort();
> +    }
>      switch (status) {
>      case 0:
>         STATUS_ALL_SUCCESS;
> @@ -5246,6 +5255,15 @@
>             STATUS_POSIX_SET(255);
>      }
>  #endif
> +    if (PL_exit_flags & PERL_EXIT_WARN) {
> +       U8 orig_exit_flags = PL_exit_flags;
> +       PL_exit_flags = (PL_exit_flags | PERL_EXIT_ABORT) &
> ~PERL_EXIT_WARN; /* Protect against reentrant calls */
> +       Perl_warn(aTHX_ "Unexpected exit failure %u", PL_statusvalue);
> +       PL_exit_flags = orig_exit_flags;
> +    }
> +    if (PL_exit_flags & PERL_EXIT_ABORT) {
> +       abort();
> +    }
>      my_exit_jump();
>  }
> 
> diff -u perl-5.8.8-1utf8valid/perl.h perl-5.8.8-2xexitwarn/perl.h
> --- perl-5.8.8-1utf8valid/perl.h        2007-06-20 09:46:51.000000000
> -0700
> +++ perl-5.8.8-2xexitwarn/perl.h        2008-03-21 14:06:48.000000000
> -0700
> @@ -2491,6 +2491,8 @@
>  /* flags in PL_exit_flags for nature of exit() */
>  #define PERL_EXIT_EXPECTED     0x01
>  #define PERL_EXIT_DESTRUCT_END  0x02  /* Run END in perl_destruct */
> +#define PERL_EXIT_WARN         0x04
> +#define PERL_EXIT_ABORT                0x08
> 
>  #ifndef MEMBER_TO_FPTR
>  #  define MEMBER_TO_FPTR(name)         name



-- 

Father Chrysostomos




nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About