[Python-checkins] cpython: Issue #11393: signal of user signal displays tracebacks even if tstate==NULL
victor.stinner
python-checkins at python.org
Fri Apr 1 15:40:03 CEST 2011
http://hg.python.org/cpython/rev/e609105dff64
changeset: 69103:e609105dff64
user: Victor Stinner <victor.stinner at haypocalc.com>
date: Fri Apr 01 15:37:12 2011 +0200
summary:
Issue #11393: signal of user signal displays tracebacks even if tstate==NULL
* faulthandler_user() displays the tracebacks of all threads even if it is
unable to get the state of the current thread
* test_faulthandler: only release the GIL in test_gil_released() check
* create check_signum() subfunction
files:
Lib/test/test_faulthandler.py | 9 ++-
Modules/faulthandler.c | 58 ++++++++++++++--------
2 files changed, 43 insertions(+), 24 deletions(-)
diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py
--- a/Lib/test/test_faulthandler.py
+++ b/Lib/test/test_faulthandler.py
@@ -8,6 +8,8 @@
import tempfile
import unittest
+TIMEOUT = 0.5
+
try:
from resource import setrlimit, RLIMIT_CORE, error as resource_error
except ImportError:
@@ -189,7 +191,7 @@
import faulthandler
output = open({filename}, 'wb')
faulthandler.enable(output)
-faulthandler._read_null(True)
+faulthandler._read_null()
""".strip().format(filename=repr(filename)),
4,
'(?:Segmentation fault|Bus error)',
@@ -199,7 +201,7 @@
self.check_fatal_error("""
import faulthandler
faulthandler.enable(all_threads=True)
-faulthandler._read_null(True)
+faulthandler._read_null()
""".strip(),
3,
'(?:Segmentation fault|Bus error)',
@@ -376,7 +378,7 @@
# Check that sleep() was not interrupted
assert (b - a) >= min_pause, "{{}} < {{}}".format(b - a, min_pause)
-timeout = 0.5
+timeout = {timeout}
repeat = {repeat}
cancel = {cancel}
if {has_filename}:
@@ -394,6 +396,7 @@
has_filename=bool(filename),
repeat=repeat,
cancel=cancel,
+ timeout=TIMEOUT,
)
trace, exitcode = self.get_output(code, filename)
trace = '\n'.join(trace)
diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c
--- a/Modules/faulthandler.c
+++ b/Modules/faulthandler.c
@@ -65,6 +65,7 @@
int fd;
int all_threads;
_Py_sighandler_t previous;
+ PyInterpreterState *interp;
} user_signal_t;
static user_signal_t *user_signals;
@@ -529,15 +530,35 @@
the thread doesn't hold the GIL. Read the thread local storage (TLS)
instead: call PyGILState_GetThisThreadState(). */
tstate = PyGILState_GetThisThreadState();
- if (tstate == NULL) {
- /* unable to get the current thread, do nothing */
- return;
- }
if (user->all_threads)
- _Py_DumpTracebackThreads(user->fd, tstate->interp, tstate);
- else
+ _Py_DumpTracebackThreads(user->fd, user->interp, tstate);
+ else {
+ if (tstate == NULL)
+ return;
_Py_DumpTraceback(user->fd, tstate);
+ }
+}
+
+static int
+check_signum(int signum)
+{
+ unsigned int i;
+
+ for (i=0; i < faulthandler_nsignals; i++) {
+ if (faulthandler_handlers[i].signum == signum) {
+ PyErr_Format(PyExc_RuntimeError,
+ "signal %i cannot be registered, "
+ "use enable() instead",
+ signum);
+ return 0;
+ }
+ }
+ if (signum < 1 || NSIG <= signum) {
+ PyErr_SetString(PyExc_ValueError, "signal number out of range");
+ return 0;
+ }
+ return 1;
}
static PyObject*
@@ -549,12 +570,12 @@
PyObject *file = NULL;
int all_threads = 0;
int fd;
- unsigned int i;
user_signal_t *user;
_Py_sighandler_t previous;
#ifdef HAVE_SIGACTION
struct sigaction action;
#endif
+ PyThreadState *tstate;
int err;
if (!PyArg_ParseTupleAndKeywords(args, kwargs,
@@ -562,19 +583,15 @@
&signum, &file, &all_threads))
return NULL;
- if (signum < 1 || NSIG <= signum) {
- PyErr_SetString(PyExc_ValueError, "signal number out of range");
+ if (!check_signum(signum))
return NULL;
- }
- for (i=0; i < faulthandler_nsignals; i++) {
- if (faulthandler_handlers[i].signum == signum) {
- PyErr_Format(PyExc_RuntimeError,
- "signal %i cannot be registered by register(), "
- "use enable() instead",
- signum);
- return NULL;
- }
+ /* The caller holds the GIL and so PyThreadState_Get() can be used */
+ tstate = PyThreadState_Get();
+ if (tstate == NULL) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "unable to get the current thread state");
+ return NULL;
}
file = faulthandler_get_fileno(file, &fd);
@@ -620,6 +637,7 @@
user->fd = fd;
user->all_threads = all_threads;
user->previous = previous;
+ user->interp = tstate->interp;
user->enabled = 1;
Py_RETURN_NONE;
@@ -651,10 +669,8 @@
if (!PyArg_ParseTuple(args, "i:unregister", &signum))
return NULL;
- if (signum < 1 || NSIG <= signum) {
- PyErr_SetString(PyExc_ValueError, "signal number out of range");
+ if (!check_signum(signum))
return NULL;
- }
user = &user_signals[signum];
change = faulthandler_unregister(user, signum);
--
Repository URL: http://hg.python.org/cpython
More information about the Python-checkins
mailing list