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