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>
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)
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;
}