: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.
# 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():
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
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 = []
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):
"""
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)
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)
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')
/* 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
#endif
} fatal_error = {0, NULL, -1, 0};
-#ifdef FAULTHANDLER_LATER
static struct {
PyObject *file;
int fd;
/* released by child thread when joined */
PyThread_type_lock running;
} thread;
-#endif
#ifdef FAULTHANDLER_USER
typedef struct {
return PyBool_FromLong(fatal_error.enabled);
}
-#ifdef FAULTHANDLER_LATER
-
static void
faulthandler_thread(void *unused)
{
cancel_dump_traceback_later();
Py_RETURN_NONE;
}
-#endif /* FAULTHANDLER_LATER */
#ifdef FAULTHANDLER_USER
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++)
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"
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,
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")},
stack.ss_size = SIGSTKSZ * 2;
#endif
-#ifdef FAULTHANDLER_LATER
memset(&thread, 0, sizeof(thread));
-#endif
if (enable) {
if (faulthandler_init_enable() < 0) {
void _PyFaulthandler_Fini(void)
{
-#ifdef FAULTHANDLER_LATER
/* later */
if (thread.cancel_event) {
cancel_dump_traceback_later();
PyThread_free_lock(thread.running);
thread.running = NULL;
}
-#endif
#ifdef FAULTHANDLER_USER
/* user */