develooper Front page | perl.perl5.porters | Postings from October 2014

Re: [perl #81074] Perl reports SIGINT handler "IGNORE" not defined inmulti-threaded apps

Thread Previous | Thread Next
From:
Leon Timmermans
Date:
October 4, 2014 00:29
Subject:
Re: [perl #81074] Perl reports SIGINT handler "IGNORE" not defined inmulti-threaded apps
Message ID:
CAHhgV8hKQdEvxk8duEucE=Rd477kKwYwnpKjCwC_Yo_xSG09xw@mail.gmail.com
On Mon, Jul 28, 2014 at 6:15 AM, Tony Cook via RT <perlbug-followup@perl.org
> wrote:

> --- a/mg.c
> +++ b/mg.c
> @@ -1353,6 +1353,15 @@ Perl_csighandler(int sig)
>      PERL_UNUSED_ARG(sip);
>      PERL_UNUSED_ARG(uap);
>  #endif
> +#ifdef USE_ITHREADS
> +    /* handle a signal received in a non-perl thread, eg. a thread
> +       created by a framework */
> +    if (!my_perl) {
> +        my_perl = PL_curinterp;
> +        PERL_SET_THX(my_perl);
> +    }
> +#endif
> +
>  #ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS
>      (void) rsignal(sig, PL_csighandlerp);
>      if (PL_sig_ignoring[sig]) return;
>

You're peeking and poking into an interpreter owned by another thread. This
is suffering from a race condition. If possible, a pthread_kill to the main
thread would be preferable I guess.


> @@ -1384,16 +1393,33 @@ Perl_csighandler(int sig)
>         (*PL_sighandlerp)(sig);
>  #endif
>      else {
> +        int pending;
>         if (!PL_psig_pend) return;
>         /* Set a flag to say this signal is pending, that is awaiting
> delivery after
>          * the current Perl opcode completes */
> -       PL_psig_pend[sig]++;
> +#ifdef USE_ITHREADS
> +        /* Only deliver to the current thread if it has a non-default
> +           signal handler set */
> +        if (PL_sighand_set && PL_sighand_set[sig]) {
> +            PL_psig_pend[sig]++;
> +            pending = ++PL_sig_pending;
> +        }
> +        else {
> +            /* no handler specific to thread, deliver to the main thread
> */
> +            dTHXa(PL_curinterp);
> +            PL_psig_pend[sig]++;
> +            pending = ++PL_sig_pending;
> +        }
>

The else block is racy too, though over a smaller scope than the previous
one.


> +
> +#ifdef USE_ITHREADS
> +    if (!isGV_with_GP(sig_ptr) && !SvROK(sig_ptr) && SvOK(sig_ptr)) {
> +        /* handle a thread receiving a signal it isn't expecting,
> +           there's a few ways this can occur, see [perl #81074] and
> +           [perl #120951] for some examples and discussion.
> +        */
> +        STRLEN siglen;
> +        const char *signame = SvPV_const(sig_ptr, siglen);
> +        if (memEQs(signame, siglen, "IGNORE")) {
> +            if (aTHX != PL_curinterp) {
> +                dTHXa(PL_curinterp);
> +                PL_psig_pend[sig]++;
> +                ++PL_sig_pending;
> +            }
> +            /* else drop it on the floor, since it's ignored */
> +
> +            goto cleanup;
> +        }
>

I don't see the logic of sending a signal to the main thread when we asked
for it to be ignored. We should probably just ignore it instead. Not that
there is a foolproof way of handling this.


> +        else if (memEQs(signame, siglen, "DEFAULT")) {
> +            if (aTHX == PL_curinterp) {
> +                /* what to do here?  The user is probably doing
> +                   something fairly strange or advanced, beat them
> +                   with a stick */
> +                PerlIO_printf(Perl_error_log, "Signal SIG%s received with
> DEFAULT signal handler set.\n",
> +                              PL_sig_name[sig]);
> +                exit(sig);
> +            }
>

I can think of at least one race condition that could cause that, but that
has existed for over 20 years and doesn't seem to be much of a deal.


> +            else {
> +                /* hopefully the main thread knows what to do with it */
> +                dTHXa(PL_curinterp);
> +                PL_psig_pend[sig]++;
> +                ++PL_sig_pending;
> +
> +                goto cleanup;
> +            }
> +        }
> +    }
> +#endif
> +
>

Again, this is racy for the previously mentioned reasons.


Also, it should be noted that your additions feature is enabled on
USE_ITHREADS, even though your solution is multiplicity based and the
problem is also a multiplicity issue. Then again, the solution I suggested
for your race condition is assuming ithreads. I'm not sure how to deal with
that, possibly by not caring.

Leon

Thread Previous | Thread Next


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