From: Ilya Zakharevich Date: Thu, 13 Feb 1997 06:44:39 +0000 (-0500) Subject: Re: Fragile signals X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=09df8c7df7dfc9853902f1fdd8a6d95f53be66fc;p=p5sagit%2Fp5-mst-13.2.git Re: Fragile signals Ilya Zakharevich writes: > > Some messages of mine get stuck in the chain: > > Nico => Debian => floor > > I repost them now: > > As you may remember, the following program > > #!/usr/bin/perl > sub foo { ++$a } > $SIG{ALRM} = sub { $run = 0 ; return }; > while (1) { > $a = 0; > $run = 1; > alarm 1; > foo while $run; > print $i++, ": $a\n"; > } > die "Not reached"; > __END__ > > will not call malloc/realloc/free in sighandler, but nevertheless it > would not run more than approx. 25 iterations. This shows that 4% of > subroutine-calling frame is not signal-safe. > > The following patch makes it run approx. twice as long (on _17) (thus Well, the following patch makes it run 4 times as long. The only failure mode I have seen was silent walking off runops(). Here is the statistics (number of iterations before failure): Before: 23, 24, 14, 22, 19, 13, 30, 11 (4 core dumps, 2 attempts to free unref scalar, 1 panic: leave-scope, 1 silent) After: 42, 936, 63, 131, 280. (all silent) It looks like handling of internal stacks needs a lot of improvement. What this patch does is only a symptomatic treatment, but it may go into 004 nevertheless (especially if one can see why op becomes 0 at some moment). I tried saving/restoring op in the handler, but this does not help... p5p-msgid: <199702130644.BAA07572@monk.mps.ohio-state.edu> --- diff --git a/mg.c b/mg.c index 77c0417..2ee52a3 100644 --- a/mg.c +++ b/mg.c @@ -1540,11 +1540,18 @@ int sig; SV *sv; CV *cv; AV *oldstack; - + int long_savestack = savestack_ix + 15 <= savestack_max; + int long_cxstack = cxstack_ix < cxstack_max - 1; + + if (long_cxtack) cxstack_ix++; /* Protect from overwrite. */ if(!psig_ptr[sig]) die("Signal SIG%s received, but no signal handler set.\n", sig_name[sig]); + /* Max number of items pushed there is 3*n or 4. We cannot fix + infinity, so we fix 4 (in fact 5): */ + if (long_savestack) savestack_ix += 5; /* Protect save in progress. */ + cv = sv_2cv(psig_ptr[sig],&st,&gv,TRUE); if (!cv || !CvROOT(cv)) { if (dowarn) @@ -1571,6 +1578,8 @@ int sig; perl_call_sv((SV*)cv, G_DISCARD); SWITCHSTACK(signalstack, oldstack); - + if (long_savestack) savestack_ix -= 5; /* Unprotect save in progress. */ + if (long_cxstack) cxstack_ix--; + return; }