[Python-checkins] bpo-38203: faulthandler.dump_traceback_later() is always available (GH-16249)

Victor Stinner webhook-mailer at python.org
Wed Sep 18 08:15:15 EDT 2019


https://github.com/python/cpython/commit/0a963fbc9c4cf4569f1eadaa2aa1229bb0081256
commit: 0a963fbc9c4cf4569f1eadaa2aa1229bb0081256
branch: master
author: Victor Stinner <vstinner at redhat.com>
committer: GitHub <noreply at github.com>
date: 2019-09-18T14:15:10+02:00
summary:

bpo-38203: faulthandler.dump_traceback_later() is always available (GH-16249)

dump_traceback_later() and cancel_dump_traceback_later() functions of
the faulthandler module are always available since Python 3.7.

files:
M Doc/library/faulthandler.rst
M Lib/test/eintrdata/eintr_tester.py
M Lib/test/libregrtest/main.py
M Lib/test/test_faulthandler.py
M Lib/test/test_regrtest.py
M Modules/faulthandler.c

diff --git a/Doc/library/faulthandler.rst b/Doc/library/faulthandler.rst
index 94ebd87639c5..b588dfa18db2 100644
--- a/Doc/library/faulthandler.rst
+++ b/Doc/library/faulthandler.rst
@@ -100,8 +100,10 @@ Dumping the tracebacks after a timeout
    :func:`cancel_dump_traceback_later` is called: see :ref:`issue with file
    descriptors <faulthandler-fd>`.
 
-   This function is implemented using a watchdog thread and therefore is not
-   available if Python is compiled with threads disabled.
+   This function is implemented using a watchdog thread.
+
+   .. versionchanged:: 3.7
+      This function is now always available.
 
    .. versionchanged:: 3.5
       Added support for passing file descriptor to this function.
diff --git a/Lib/test/eintrdata/eintr_tester.py b/Lib/test/eintrdata/eintr_tester.py
index 404934ce97a2..4e0e30596f5a 100644
--- a/Lib/test/eintrdata/eintr_tester.py
+++ b/Lib/test/eintrdata/eintr_tester.py
@@ -57,9 +57,8 @@ def setUp(self):
 
         # Use faulthandler as watchdog to debug when a test hangs
         # (timeout of 10 minutes)
-        if hasattr(faulthandler, 'dump_traceback_later'):
-            faulthandler.dump_traceback_later(10 * 60, exit=True,
-                                              file=sys.__stderr__)
+        faulthandler.dump_traceback_later(10 * 60, exit=True,
+                                          file=sys.__stderr__)
 
     @staticmethod
     def stop_alarm():
@@ -68,8 +67,7 @@ def stop_alarm():
     def tearDown(self):
         self.stop_alarm()
         signal.signal(signal.SIGALRM, self.orig_handler)
-        if hasattr(faulthandler, 'cancel_dump_traceback_later'):
-            faulthandler.cancel_dump_traceback_later()
+        faulthandler.cancel_dump_traceback_later()
 
     def subprocess(self, *args, **kw):
         cmd_args = (sys.executable, '-c') + args
diff --git a/Lib/test/libregrtest/main.py b/Lib/test/libregrtest/main.py
index 47c60126ea65..299700686928 100644
--- a/Lib/test/libregrtest/main.py
+++ b/Lib/test/libregrtest/main.py
@@ -164,11 +164,6 @@ def display_progress(self, test_index, text):
     def parse_args(self, kwargs):
         ns = _parse_args(sys.argv[1:], **kwargs)
 
-        if ns.timeout and not hasattr(faulthandler, 'dump_traceback_later'):
-            print("Warning: The timeout option requires "
-                  "faulthandler.dump_traceback_later", file=sys.stderr)
-            ns.timeout = None
-
         if ns.xmlpath:
             support.junit_xml_list = self.testsuite_xml = []
 
diff --git a/Lib/test/test_faulthandler.py b/Lib/test/test_faulthandler.py
index 24487446f25b..a4427a537d1f 100644
--- a/Lib/test/test_faulthandler.py
+++ b/Lib/test/test_faulthandler.py
@@ -535,8 +535,6 @@ def test_dump_traceback_threads_file(self):
         with temporary_filename() as filename:
             self.check_dump_traceback_threads(filename)
 
-    @unittest.skipIf(not hasattr(faulthandler, 'dump_traceback_later'),
-                     'need faulthandler.dump_traceback_later()')
     def check_dump_traceback_later(self, repeat=False, cancel=False, loops=1,
                                    *, filename=None, fd=None):
         """
@@ -744,9 +742,8 @@ def test_stderr_None(self):
             faulthandler.enable()
         with self.check_stderr_none():
             faulthandler.dump_traceback()
-        if hasattr(faulthandler, 'dump_traceback_later'):
-            with self.check_stderr_none():
-                faulthandler.dump_traceback_later(1e-3)
+        with self.check_stderr_none():
+            faulthandler.dump_traceback_later(1e-3)
         if hasattr(faulthandler, "register"):
             with self.check_stderr_none():
                 faulthandler.register(signal.SIGUSR1)
diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py
index ef2ee90d2a0d..50911995ad1e 100644
--- a/Lib/test/test_regrtest.py
+++ b/Lib/test/test_regrtest.py
@@ -54,8 +54,6 @@ def test_help(self):
                     libregrtest._parse_args([opt])
                 self.assertIn('Run Python regression tests.', out.getvalue())
 
-    @unittest.skipUnless(hasattr(faulthandler, 'dump_traceback_later'),
-                         "faulthandler.dump_traceback_later() required")
     def test_timeout(self):
         ns = libregrtest._parse_args(['--timeout', '4.2'])
         self.assertEqual(ns.timeout, 4.2)
@@ -572,8 +570,7 @@ def setUp(self):
         self.python_args = ['-Wd', '-E', '-bb']
         self.regrtest_args = ['-uall', '-rwW',
                               '--testdir=%s' % self.tmptestdir]
-        if hasattr(faulthandler, 'dump_traceback_later'):
-            self.regrtest_args.extend(('--timeout', '3600', '-j4'))
+        self.regrtest_args.extend(('--timeout', '3600', '-j4'))
         if sys.platform == 'win32':
             self.regrtest_args.append('-n')
 
diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c
index 011ab5fa28f2..129a104dba3f 100644
--- a/Modules/faulthandler.c
+++ b/Modules/faulthandler.c
@@ -19,8 +19,6 @@
 /* Allocate at maximum 100 MiB of the stack to raise the stack overflow */
 #define STACK_OVERFLOW_MAX_SIZE (100 * 1024 * 1024)
 
-#define FAULTHANDLER_LATER
-
 #ifndef MS_WINDOWS
    /* register() is useless on Windows, because only SIGSEGV, SIGABRT and
       SIGILL can be handled by the process, and these signals can only be used
@@ -60,7 +58,6 @@ static struct {
 #endif
 } fatal_error = {0, NULL, -1, 0};
 
-#ifdef FAULTHANDLER_LATER
 static struct {
     PyObject *file;
     int fd;
@@ -77,7 +74,6 @@ static struct {
     /* released by child thread when joined */
     PyThread_type_lock running;
 } thread;
-#endif
 
 #ifdef FAULTHANDLER_USER
 typedef struct {
@@ -589,8 +585,6 @@ faulthandler_is_enabled(PyObject *self, PyObject *Py_UNUSED(ignored))
     return PyBool_FromLong(fatal_error.enabled);
 }
 
-#ifdef FAULTHANDLER_LATER
-
 static void
 faulthandler_thread(void *unused)
 {
@@ -790,7 +784,6 @@ faulthandler_cancel_dump_traceback_later_py(PyObject *self,
     cancel_dump_traceback_later();
     Py_RETURN_NONE;
 }
-#endif  /* FAULTHANDLER_LATER */
 
 
 #ifdef FAULTHANDLER_USER
@@ -1230,9 +1223,7 @@ faulthandler_stack_overflow(PyObject *self, PyObject *Py_UNUSED(ignored))
 static int
 faulthandler_traverse(PyObject *module, visitproc visit, void *arg)
 {
-#ifdef FAULTHANDLER_LATER
     Py_VISIT(thread.file);
-#endif
 #ifdef FAULTHANDLER_USER
     if (user_signals != NULL) {
         for (size_t signum=0; signum < NSIG; signum++)
@@ -1273,7 +1264,6 @@ static PyMethodDef module_methods[] = {
      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
     {"dump_traceback_later",
      (PyCFunction)(void(*)(void))faulthandler_dump_traceback_later, METH_VARARGS|METH_KEYWORDS,
      PyDoc_STR("dump_traceback_later(timeout, repeat=False, file=sys.stderrn, exit=False):\n"
@@ -1284,8 +1274,6 @@ static PyMethodDef module_methods[] = {
      faulthandler_cancel_dump_traceback_later_py, METH_NOARGS,
      PyDoc_STR("cancel_dump_traceback_later():\ncancel the previous call "
                "to dump_traceback_later().")},
-#endif
-
 #ifdef FAULTHANDLER_USER
     {"register",
      (PyCFunction)(void(*)(void))faulthandler_register_py, METH_VARARGS|METH_KEYWORDS,
@@ -1298,7 +1286,6 @@ static PyMethodDef module_methods[] = {
      PyDoc_STR("unregister(signum): unregister the handler of the signal "
                 "'signum' registered by register()")},
 #endif
-
     {"_read_null", faulthandler_read_null, METH_NOARGS,
      PyDoc_STR("_read_null(): read from NULL, raise "
                "a SIGSEGV or SIGBUS signal depending on the platform")},
@@ -1399,9 +1386,7 @@ _PyFaulthandler_Init(int enable)
     stack.ss_size = SIGSTKSZ * 2;
 #endif
 
-#ifdef FAULTHANDLER_LATER
     memset(&thread, 0, sizeof(thread));
-#endif
 
     if (enable) {
         if (faulthandler_init_enable() < 0) {
@@ -1413,7 +1398,6 @@ _PyFaulthandler_Init(int enable)
 
 void _PyFaulthandler_Fini(void)
 {
-#ifdef FAULTHANDLER_LATER
     /* later */
     if (thread.cancel_event) {
         cancel_dump_traceback_later();
@@ -1425,7 +1409,6 @@ void _PyFaulthandler_Fini(void)
         PyThread_free_lock(thread.running);
         thread.running = NULL;
     }
-#endif
 
 #ifdef FAULTHANDLER_USER
     /* user */



More information about the Python-checkins mailing list