]> granicus.if.org Git - python/commitdiff
faulthandler: dump all threads by default
authorVictor Stinner <victor.stinner@haypocalc.com>
Sat, 7 May 2011 10:43:00 +0000 (12:43 +0200)
committerVictor Stinner <victor.stinner@haypocalc.com>
Sat, 7 May 2011 10:43:00 +0000 (12:43 +0200)
 * Set the default value of all_threads arguments to True
 * Py_FatalError() dumps all threads, instead of only the current thread

Dump only the current thread is not reliable. In some cases, Python is unable
to retrieve the state of the current thread and so is unable to dump the
traceback. faulthandler keeps a reference to the interpreter and so is always
able to dump the traceback of all threads.

Doc/library/faulthandler.rst
Lib/test/test_faulthandler.py
Modules/faulthandler.c
Python/pythonrun.c

index c0b662502f484b80add55a30f89d9934231109d7..0c00f8f298c8f5a96b11ca85dbb8178cb495232b 100644 (file)
@@ -36,21 +36,22 @@ when Python is blocked (e.g. deadlock).
 Dump the traceback
 ------------------
 
-.. function:: dump_traceback(file=sys.stderr, all_threads=False)
+.. function:: dump_traceback(file=sys.stderr, all_threads=True)
 
-   Dump the traceback of the current thread, or of all threads if *all_threads*
-   is ``True``, into *file*.
+   Dump the traceback of all threads, or of the current thread if *all_threads*
+   is ``False``, into *file*.
 
 
 Fault handler state
 -------------------
 
-.. function:: enable(file=sys.stderr, all_threads=False)
+.. function:: enable(file=sys.stderr, all_threads=True)
 
    Enable the fault handler: install handlers for :const:`SIGSEGV`,
    :const:`SIGFPE`, :const:`SIGABRT`, :const:`SIGBUS` and :const:`SIGILL`
-   signals to dump the Python traceback. It dumps the traceback of the current
-   thread, or all threads if *all_threads* is ``True``, into *file*.
+   signals to dump the Python traceback. It dumps the traceback of the all
+   threads, or of the current thread if *all_threads* is ``False``, into
+   *file*.
 
 .. function:: disable()
 
@@ -86,11 +87,11 @@ Dump the tracebacks after a timeout
 Dump the traceback on a user signal
 -----------------------------------
 
-.. function:: register(signum, file=sys.stderr, all_threads=False)
+.. function:: register(signum, file=sys.stderr, all_threads=True)
 
    Register a user signal: install a handler for the *signum* signal to dump
-   the traceback of the current thread, or of all threads if *all_threads* is
-   ``True``, into *file*.
+   the traceback of all threads, or of the current thread if *all_threads* is
+   ``False``, into *file*.
 
    Not available on Windows.
 
@@ -123,7 +124,7 @@ Example of a segmentation fault on Linux: ::
     >>> ctypes.string_at(0)
     Fatal Python error: Segmentation fault
 
-    Traceback (most recent call first):
+    Current thread 0x00007fb899f39700:
       File "/home/python/cpython/Lib/ctypes/__init__.py", line 486 in string_at
       File "<stdin>", line 1 in <module>
     Segmentation fault
index d08347d90ea00a15a4ee964b8ba6a8433e67c3a1..dbc19178a1c5fac3bc023c2ea0c6aea0ca1105b2 100644 (file)
@@ -75,7 +75,7 @@ class FaultHandlerTests(unittest.TestCase):
         return output.splitlines(), exitcode
 
     def check_fatal_error(self, code, line_number, name_regex,
-                          filename=None, all_threads=False, other_regex=None):
+                          filename=None, all_threads=True, other_regex=None):
         """
         Check that the fault handler for fatal errors is enabled and check the
         traceback from the child process output.
@@ -204,15 +204,15 @@ faulthandler._read_null()
                 '(?:Segmentation fault|Bus error)',
                 filename=filename)
 
-    def test_enable_threads(self):
+    def test_enable_single_thread(self):
         self.check_fatal_error("""
 import faulthandler
-faulthandler.enable(all_threads=True)
+faulthandler.enable(all_threads=False)
 faulthandler._read_null()
 """.strip(),
             3,
             '(?:Segmentation fault|Bus error)',
-            all_threads=True)
+            all_threads=False)
 
     def test_disable(self):
         code = """
@@ -252,9 +252,9 @@ import faulthandler
 def funcB():
     if {has_filename}:
         with open({filename}, "wb") as fp:
-            faulthandler.dump_traceback(fp)
+            faulthandler.dump_traceback(fp, all_threads=False)
     else:
-        faulthandler.dump_traceback()
+        faulthandler.dump_traceback(all_threads=False)
 
 def funcA():
     funcB()
index 8f83ab8e41bccc03c96f8193bead2d5371e9ff7c..6041485b54ad6aa2777a0f4bcabc150cab4e86f0 100644 (file)
@@ -186,7 +186,7 @@ faulthandler_dump_traceback_py(PyObject *self,
 {
     static char *kwlist[] = {"file", "all_threads", NULL};
     PyObject *file = NULL;
-    int all_threads = 0;
+    int all_threads = 1;
     PyThreadState *tstate;
     const char *errmsg;
     int fd;
@@ -306,7 +306,7 @@ faulthandler_enable(PyObject *self, PyObject *args, PyObject *kwargs)
 {
     static char *kwlist[] = {"file", "all_threads", NULL};
     PyObject *file = NULL;
-    int all_threads = 0;
+    int all_threads = 1;
     unsigned int i;
     fault_handler_t *handler;
 #ifdef HAVE_SIGACTION
@@ -648,7 +648,7 @@ faulthandler_register(PyObject *self,
     static char *kwlist[] = {"signum", "file", "all_threads", NULL};
     int signum;
     PyObject *file = NULL;
-    int all_threads = 0;
+    int all_threads = 1;
     int fd;
     user_signal_t *user;
     _Py_sighandler_t previous;
@@ -916,7 +916,7 @@ PyDoc_STRVAR(module_doc,
 static PyMethodDef module_methods[] = {
     {"enable",
      (PyCFunction)faulthandler_enable, METH_VARARGS|METH_KEYWORDS,
-     PyDoc_STR("enable(file=sys.stderr, all_threads=False): "
+     PyDoc_STR("enable(file=sys.stderr, all_threads=True): "
                "enable the fault handler")},
     {"disable", (PyCFunction)faulthandler_disable_py, METH_NOARGS,
      PyDoc_STR("disable(): disable the fault handler")},
@@ -924,7 +924,7 @@ static PyMethodDef module_methods[] = {
      PyDoc_STR("is_enabled()->bool: check if the handler is enabled")},
     {"dump_traceback",
      (PyCFunction)faulthandler_dump_traceback_py, METH_VARARGS|METH_KEYWORDS,
-     PyDoc_STR("dump_traceback(file=sys.stderr, all_threads=False): "
+     PyDoc_STR("dump_traceback(file=sys.stderr, all_threads=True): "
                "dump the traceback of the current thread, or of all threads "
                "if all_threads is True, into file")},
 #ifdef FAULTHANDLER_LATER
@@ -943,7 +943,7 @@ static PyMethodDef module_methods[] = {
 #ifdef FAULTHANDLER_USER
     {"register",
      (PyCFunction)faulthandler_register, METH_VARARGS|METH_KEYWORDS,
-     PyDoc_STR("register(signum, file=sys.stderr, all_threads=False): "
+     PyDoc_STR("register(signum, file=sys.stderr, all_threads=True): "
                "register an handler for the signal 'signum': dump the "
                "traceback of the current thread, or of all threads if "
                "all_threads is True, into file")},
index ebc4f1cf17d5b05bf27857a0dd891618a76538d6..6ebc823b80cb2cc9435f4dcd62e14cdd293c1bfe 100644 (file)
@@ -2144,7 +2144,7 @@ Py_FatalError(const char *msg)
         if (tstate != NULL) {
             fputc('\n', stderr);
             fflush(stderr);
-            _Py_DumpTraceback(fd, tstate);
+            _Py_DumpTracebackThreads(fd, tstate->interp, tstate);
         }
         _PyFaulthandler_Fini();
     }