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