292b33
From 13716dc35cd0869b98bd30cebbdeb8d48ab07a8b Mon Sep 17 00:00:00 2001
292b33
From: Nicholas Clark <nick@ccl4.org>
292b33
Date: Sat, 14 Apr 2012 15:51:33 +0200
292b33
Subject: [PATCH] Remove PERL_ASYNC_CHECK() from Perl_leave_scope().
292b33
292b33
PERL_ASYNC_CHECK() was added to Perl_leave_scope() as part of commit
292b33
f410a2119920dd04, which moved signal dispatch from the runloop to
292b33
control flow ops, to mitigate nearly all of the speed cost of safe
292b33
signals.
292b33
292b33
The assumption was that scope exit was a safe place to dispatch signals.
292b33
However, this is not true, as parts of the regex engine call
292b33
leave_scope(), the regex engine stores some state in per-interpreter
292b33
variables, and code called within signal handlers can change these
292b33
values.
292b33
292b33
Hence remove the call to PERL_ASYNC_CHECK() from Perl_leave_scope(), and
292b33
add it explicitly in the various OPs which were relying on their call to
292b33
leave_scope() to dispatch any pending signals. Also add a
292b33
PERL_ASYNC_CHECK() to the exit of the runloop, which ensures signals
292b33
still dispatch from S_sortcv() and S_sortcv_stacked(), as well as
292b33
addressing one of the concerns in the commit message of
292b33
f410a2119920dd04:
292b33
292b33
    Subtle bugs might remain - there might be constructions that enter
292b33
    the runloop (where signals used to be dispatched) but don't contain
292b33
    any PERL_ASYNC_CHECK() calls themselves.
292b33
292b33
Finally, move the PERL_ASYNC_CHECK(); added by that commit to pp_goto to
292b33
the end of the function, to be consistent with the positioning of all
292b33
other PERL_ASYNC_CHECK() calls - at the beginning or end of OP
292b33
functions, hence just before the return to or just after the call from
292b33
the runloop, and hence effectively at the same point as the previous
292b33
location of PERL_ASYNC_CHECK() in the runloop.
292b33
---
292b33
 dump.c   |  1 +
292b33
 pp_ctl.c | 11 ++++++++++-
292b33
 run.c    |  1 +
292b33
 scope.c  |  2 --
292b33
 4 files changed, 12 insertions(+), 3 deletions(-)
292b33
292b33
diff --git a/dump.c b/dump.c
292b33
index b238ee0..d770a65 100644
292b33
--- a/dump.c
292b33
+++ b/dump.c
292b33
@@ -2118,6 +2118,7 @@ Perl_runops_debug(pTHX)
292b33
 	}
292b33
     } while ((PL_op = PL_op->op_ppaddr(aTHX)));
292b33
     DEBUG_l(Perl_deb(aTHX_ "leaving RUNOPS level\n"));
292b33
+    PERL_ASYNC_CHECK();
292b33
 
292b33
     TAINT_NOT;
292b33
     return 0;
292b33
diff --git a/pp_ctl.c b/pp_ctl.c
292b33
index fd92efa..6206a25 100644
292b33
--- a/pp_ctl.c
292b33
+++ b/pp_ctl.c
292b33
@@ -377,6 +377,7 @@ PP(pp_substcont)
292b33
 	    TAINT_NOT;
292b33
 	    LEAVE_SCOPE(cx->sb_oldsave);
292b33
 	    POPSUBST(cx);
292b33
+	    PERL_ASYNC_CHECK();
292b33
 	    RETURNOP(pm->op_next);
292b33
 	    /* NOTREACHED */
292b33
 	}
292b33
@@ -2732,6 +2733,7 @@ PP(pp_next)
292b33
     if (PL_scopestack_ix < inner)
292b33
 	leave_scope(PL_scopestack[PL_scopestack_ix]);
292b33
     PL_curcop = cx->blk_oldcop;
292b33
+    PERL_ASYNC_CHECK();
292b33
     return (cx)->blk_loop.my_op->op_nextop;
292b33
 }
292b33
 
292b33
@@ -2774,6 +2776,7 @@ PP(pp_redo)
292b33
     LEAVE_SCOPE(oldsave);
292b33
     FREETMPS;
292b33
     PL_curcop = cx->blk_oldcop;
292b33
+    PERL_ASYNC_CHECK();
292b33
     return redo_op;
292b33
 }
292b33
 
292b33
@@ -2978,6 +2981,7 @@ PP(pp_goto)
292b33
 		PUTBACK;
292b33
 		(void)(*CvXSUB(cv))(aTHX_ cv);
292b33
 		LEAVE;
292b33
+		PERL_ASYNC_CHECK();
292b33
 		return retop;
292b33
 	    }
292b33
 	    else {
292b33
@@ -3049,6 +3053,7 @@ PP(pp_goto)
292b33
 			}
292b33
 		    }
292b33
 		}
292b33
+		PERL_ASYNC_CHECK();
292b33
 		RETURNOP(CvSTART(cv));
292b33
 	    }
292b33
 	}
292b33
@@ -3209,6 +3214,7 @@ PP(pp_goto)
292b33
 	PL_do_undump = FALSE;
292b33
     }
292b33
 
292b33
+    PERL_ASYNC_CHECK();
292b33
     RETURNOP(retop);
292b33
 }
292b33
 
292b33
@@ -5129,10 +5135,13 @@ PP(pp_leavewhen)
292b33
 	    leave_scope(PL_scopestack[PL_scopestack_ix]);
292b33
 	PL_curcop = cx->blk_oldcop;
292b33
 
292b33
+	PERL_ASYNC_CHECK();
292b33
 	return cx->blk_loop.my_op->op_nextop;
292b33
     }
292b33
-    else
292b33
+    else {
292b33
+	PERL_ASYNC_CHECK();
292b33
 	RETURNOP(cx->blk_givwhen.leave_op);
292b33
+    }
292b33
 }
292b33
 
292b33
 PP(pp_continue)
292b33
diff --git a/run.c b/run.c
292b33
index 7c1d0aa..774852d 100644
292b33
--- a/run.c
292b33
+++ b/run.c
292b33
@@ -40,6 +40,7 @@ Perl_runops_standard(pTHX)
292b33
     register OP *op = PL_op;
292b33
     while ((PL_op = op = op->op_ppaddr(aTHX))) {
292b33
     }
292b33
+    PERL_ASYNC_CHECK();
292b33
 
292b33
     TAINT_NOT;
292b33
     return 0;
292b33
diff --git a/scope.c b/scope.c
292b33
index ffd0552..121d1f7 100644
292b33
--- a/scope.c
292b33
+++ b/scope.c
292b33
@@ -1168,8 +1168,6 @@ Perl_leave_scope(pTHX_ I32 base)
292b33
     }
292b33
 
292b33
     PL_tainted = was;
292b33
-
292b33
-    PERL_ASYNC_CHECK();
292b33
 }
292b33
 
292b33
 void
292b33
-- 
292b33
1.8.1.4
292b33