develooper Front page | perl.perl5.porters | Postings from February 2003

FW: [perl #20613] Perl_magic_setsig/clearsig problems (patch included)

From:
Anders Johnson
Date:
February 5, 2003 01:06
Subject:
FW: [perl #20613] Perl_magic_setsig/clearsig problems (patch included)
Message ID:
001c01c2cc86$7034aee0$9800a8c0@wis.com
[I tried to send this yesterday, but our email server was hosed. Sorry
if this is a duplicate.]

Nick Ing-Simmons:
> I don't fully grasp what the problem is yet. The "safe signals" code 
> in 5.8 should make the above _less_ necessary. Signals should only 
> be asynchronously messing with a always allocated array of counts. All
> access to perl SVs etc. should be synchronous - so what is 
> getting in during the decrement? And which bit of code let it?

This particular problems arises from the DESTROY method(s) associated
with the scalar being freed through SvREFCNT_dec. Signals get sampled
inside DESTROY methods, so calls to SvREFCNT_dec can result in
PERL_ASYNC_CHECK() being called. The test case included in the patch
illustrates the problem.

The sigprocmask() stuff in the original patch is actually bogus because
of the new "safe signals" code. Sorry about that. However, something
similar is needed to fix one of the related problems (see below).

Nick Ing-Simmons:
> If the signal had arrived slightly later (machine busier)
> it would have gone to DEFAULT handler - so changing handlers when 
> signals maybe in the pipe is source of the "badness".

Let me try to predict what will happen (and since this is difficult to
reproduce reliably, I'll let you correct me if I'm wrong):

1. We enter Perl_magic_setsig() with a new disposition of "DEFAULT".
2. The signal arrives, setting PL_sig_pending and PL_psig_pend[sig].
3. PL_psig_ptr[sig] and PL_psig_name[sig] are set to "DEFAULT".
4. The signal is redispositioned to SIG_DFL.
5. We return from Perl_magic_setsig(), and back into the Perl code.
6. At some point soon thereafter, Perl_despatch_signal() is called,
which
   calls Perl_sighandler() on behalf of the signal.
7. "SIGxxx handler \"DEFAULT\" not defined." (I call this badness.)

It seems to me that fundamentally you need to prevent #2 from happening,
or you'll be in trouble. You could require the Perl code to call
POSIX::sigprocmask() before assigning to %SIG, but that's pretty ugly.
My vote would be to have Perl_magic_setsig() and Perl_magic_clearsig()
take care of this for you. (I have a patch for this, but I'd prefer to
resolve the issues before we start shooting various patches back and
forth.)

Nick Ing-Simmons:
> Can you explain some more?

That bit about destructors not throwing is a subtle point that C++'ers
have debated at some length, but ultimately the only clean solution is
that it should never, ever happen. Ever. Here's an example:

Consider an object that represents a temporary file. When the object
goes out of scope, you require the temporary file to be removed *without
exception*. Now suppose that you just reached the end of the block
containing the object, and you're in the middle of the object's DESTROY
method, after you've done some stuff but before the file has been
removed. Then a signal arrives and its handler die()s. Now you're in a
world of hurt, because either A) you've already decremented the object's
reference count, and the file isn't going to be removed at all, or B)
the die() causes the reference count to go to zero, in which case you'll
restart the DESTROY method from the beginning, which is bad because the
object is probably in an inconsistent state.

There are lots of other ways for this to cause problems, including
leaking gobs of memory and so forth. But if you can take care of this
example, then you're probably on the right track.

I can think of two distinct ways to attack the problem, the first of
which is that "$^E" stuff I mentioned earlier. The second would be to
guarantee that DESTROY and STORE methods (STORE can get called when a
tie'd local goes out of scope) always get restarted, and then to require
those methods to put a "local $SIG{...}" or "eval" around critical code.
(This second approach leads us back to handlers that can accumulate
signals, which is what exposes that first problem.)

Thanks,
&ers





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