summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2007-12-10 23:00:12 (GMT)
committerGuido van Rossum <guido@python.org>2007-12-10 23:00:12 (GMT)
commit137c49ce6a69acb2e4c649d001882e4f7a4ee45a (patch)
tree282497303842a02531febb4c6e40321f9c760bd1
parent284d9276250d78e8dfe59dc9a64cb0422265148b (diff)
downloadcpython-137c49ce6a69acb2e4c649d001882e4f7a4ee45a.zip
cpython-137c49ce6a69acb2e4c649d001882e4f7a4ee45a.tar.gz
cpython-137c49ce6a69acb2e4c649d001882e4f7a4ee45a.tar.bz2
Patch #1643738 by Ulisses Furquim -- make the is_tripped variable
in signalmodule.c more robust. Includes Martin von Loewis's suggestion to set is_tripped after .tripped.
-rw-r--r--Misc/ACKS1
-rw-r--r--Modules/signalmodule.c31
2 files changed, 27 insertions, 5 deletions
diff --git a/Misc/ACKS b/Misc/ACKS
index 5925045..65ee9e7 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -223,6 +223,7 @@ Tadayoshi Funaba
Gyro Funch
Peter Funk
Geoff Furnish
+Ulisses Furquim
Lele Gaifax
Santiago Gala
Yitzchak Gale
diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c
index a729604..9d223d5 100644
--- a/Modules/signalmodule.c
+++ b/Modules/signalmodule.c
@@ -75,7 +75,8 @@ static struct {
PyObject *func;
} Handlers[NSIG];
-static int is_tripped = 0; /* Speed up sigcheck() when none tripped */
+/* Speed up sigcheck() when none tripped */
+static volatile sig_atomic_t is_tripped = 0;
static PyObject *DefaultHandler;
static PyObject *IgnoreHandler;
@@ -122,8 +123,10 @@ signal_handler(int sig_num)
/* See NOTES section above */
if (getpid() == main_pid) {
#endif
- is_tripped++;
Handlers[sig_num].tripped = 1;
+ /* Set is_tripped after setting .tripped, as it gets
+ cleared in PyErr_CheckSignals() before .tripped. */
+ is_tripped = 1;
Py_AddPendingCall(checksignals_witharg, NULL);
#ifdef WITH_THREAD
}
@@ -597,13 +600,31 @@ PyErr_CheckSignals(void)
if (!is_tripped)
return 0;
+
#ifdef WITH_THREAD
if (PyThread_get_thread_ident() != main_thread)
return 0;
#endif
+
+ /*
+ * The is_stripped variable is meant to speed up the calls to
+ * PyErr_CheckSignals (both directly or via pending calls) when no
+ * signal has arrived. This variable is set to 1 when a signal arrives
+ * and it is set to 0 here, when we know some signals arrived. This way
+ * we can run the registered handlers with no signals blocked.
+ *
+ * NOTE: with this approach we can have a situation where is_tripped is
+ * 1 but we have no more signals to handle (Handlers[i].tripped
+ * is 0 for every signal i). This won't do us any harm (except
+ * we're gonna spent some cycles for nothing). This happens when
+ * we receive a signal i after we zero is_tripped and before we
+ * check Handlers[i].tripped.
+ */
+ is_tripped = 0;
+
if (!(f = (PyObject *)PyEval_GetFrame()))
f = Py_None;
-
+
for (i = 1; i < NSIG; i++) {
if (Handlers[i].tripped) {
PyObject *result = NULL;
@@ -621,7 +642,7 @@ PyErr_CheckSignals(void)
Py_DECREF(result);
}
}
- is_tripped = 0;
+
return 0;
}
@@ -632,7 +653,7 @@ PyErr_CheckSignals(void)
void
PyErr_SetInterrupt(void)
{
- is_tripped++;
+ is_tripped = 1;
Handlers[SIGINT].tripped = 1;
Py_AddPendingCall((int (*)(void *))PyErr_CheckSignals, NULL);
}