summaryrefslogtreecommitdiff
path: root/mg.c
diff options
context:
space:
mode:
Diffstat (limited to 'mg.c')
-rw-r--r--mg.c96
1 files changed, 82 insertions, 14 deletions
diff --git a/mg.c b/mg.c
index eb5888605f..7c7ea2a97d 100644
--- a/mg.c
+++ b/mg.c
@@ -1353,14 +1353,7 @@ MAGIC* mg;
osname = Nullch;
break;
case '\020': /* ^P */
- i = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
- if (i != perldb) {
- if (perldb)
- oldlastpm = curpm;
- else
- curpm = oldlastpm;
- }
- perldb = i;
+ perldb = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv);
break;
case '\024': /* ^T */
#ifdef BIG_TIME
@@ -1664,6 +1657,21 @@ char *sig;
return 0;
}
+static SV* sig_sv;
+
+static void
+unwind_handler_stack(p)
+ void *p;
+{
+ U32 flags = *(U32*)p;
+
+ if (flags & 1)
+ savestack_ix -= 5; /* Unprotect save in progress. */
+ /* cxstack_ix-- Not needed, die already unwound it. */
+ if (flags & 64)
+ SvREFCNT_dec(sig_sv);
+}
+
Signal_t
sighandler(sig)
int sig;
@@ -1671,15 +1679,56 @@ int sig;
dSP;
GV *gv;
HV *st;
- SV *sv;
+ SV *sv, *tSv = Sv;
CV *cv;
AV *oldstack;
-
+ OP *myop = op;
+ U32 flags = 0;
+ I32 o_save_i = savestack_ix, type;
+ CONTEXT *cx;
+ XPV *tXpv = Xpv;
+
+ if (savestack_ix + 15 <= savestack_max)
+ flags |= 1;
+ if (cxstack_ix < cxstack_max - 2)
+ flags |= 2;
+ if (markstack_ptr < markstack_max - 2)
+ flags |= 4;
+ if (retstack_ix < retstack_max - 2)
+ flags |= 8;
+ if (scopestack_ix < scopestack_max - 3)
+ flags |= 16;
+
+ if (flags & 2) { /* POPBLOCK may decrease cxstack too early. */
+ cxstack_ix++; /* Protect from overwrite. */
+ cx = &cxstack[cxstack_ix];
+ type = cx->cx_type; /* Can be during partial write. */
+ cx->cx_type = CXt_NULL; /* Make it safe for unwind. */
+ }
if (!psig_ptr[sig])
die("Signal SIG%s received, but no signal handler set.\n",
sig_name[sig]);
- cv = sv_2cv(psig_ptr[sig],&st,&gv,TRUE);
+ /* Max number of items pushed there is 3*n or 4. We cannot fix
+ infinity, so we fix 4 (in fact 5): */
+ if (flags & 1) {
+ savestack_ix += 5; /* Protect save in progress. */
+ o_save_i = savestack_ix;
+ SAVEDESTRUCTOR(unwind_handler_stack, (void*)&flags);
+ }
+ if (flags & 4)
+ markstack_ptr++; /* Protect mark. */
+ if (flags & 8) {
+ retstack_ix++;
+ retstack[retstack_ix] = NULL;
+ }
+ if (flags & 16)
+ scopestack_ix += 1;
+ /* sv_2cv is too complicated, try a simpler variant first: */
+ if (!SvROK(psig_ptr[sig]) || !(cv = (CV*)SvRV(psig_ptr[sig]))
+ || SvTYPE(cv) != SVt_PVCV)
+ cv = sv_2cv(psig_ptr[sig],&st,&gv,TRUE);
+
if (!cv || !CvROOT(cv)) {
if (dowarn)
warn("SIG%s handler \"%s\" not defined.\n",
@@ -1692,9 +1741,11 @@ int sig;
AvFILL(signalstack) = 0;
SWITCHSTACK(curstack, signalstack);
- if(psig_name[sig])
+ if(psig_name[sig]) {
sv = SvREFCNT_inc(psig_name[sig]);
- else {
+ flags |= 64;
+ sig_sv = sv;
+ } else {
sv = sv_newmortal();
sv_setpv(sv,sig_name[sig]);
}
@@ -1705,6 +1756,23 @@ int sig;
perl_call_sv((SV*)cv, G_DISCARD);
SWITCHSTACK(signalstack, oldstack);
-
+ if (flags & 1)
+ savestack_ix -= 8; /* Unprotect save in progress. */
+ if (flags & 2) {
+ cxstack[cxstack_ix].cx_type = type;
+ cxstack_ix -= 1;
+ }
+ if (flags & 4)
+ markstack_ptr--;
+ if (flags & 8)
+ retstack_ix--;
+ if (flags & 16)
+ scopestack_ix -= 1;
+ if (flags & 64)
+ SvREFCNT_dec(sv);
+ op = myop; /* Apparently not needed... */
+
+ Sv = tSv; /* Restore global temporaries. */
+ Xpv = tXpv;
return;
}