Issue #23566: enable(), register(), dump_traceback() and dump_traceback_later()

functions of faulthandler now accept file descriptors. Patch by Wei Wu.
This commit is contained in:
Victor Stinner 2015-03-12 15:32:03 +01:00
parent ebaa81f3b1
commit 95bb714ff7
5 changed files with 172 additions and 78 deletions

View file

@ -133,32 +133,46 @@ static stack_t stack;
call its flush() method.
If file is NULL or Py_None, use sys.stderr as the new file.
If file is an integer, it will be treated as file descriptor.
On success, return the new file and write the file descriptor into *p_fd.
On error, return NULL. */
On success, return the file descriptor and write the new file into *file_ptr.
On error, return -1. */
static PyObject*
faulthandler_get_fileno(PyObject *file, int *p_fd)
static int
faulthandler_get_fileno(PyObject **file_ptr)
{
PyObject *result;
long fd_long;
int fd;
PyObject *file = *file_ptr;
if (file == NULL || file == Py_None) {
file = _PySys_GetObjectId(&PyId_stderr);
if (file == NULL) {
PyErr_SetString(PyExc_RuntimeError, "unable to get sys.stderr");
return NULL;
return -1;
}
if (file == Py_None) {
PyErr_SetString(PyExc_RuntimeError, "sys.stderr is None");
return NULL;
return -1;
}
}
else if (PyLong_Check(file)) {
fd = _PyLong_AsInt(file);
if (fd == -1 && PyErr_Occurred())
return -1;
if (fd < 0 || !_PyVerify_fd(fd)) {
PyErr_SetString(PyExc_ValueError,
"file is not a valid file descripter");
return -1;
}
*file_ptr = NULL;
return fd;
}
result = _PyObject_CallMethodId(file, &PyId_fileno, "");
if (result == NULL)
return NULL;
return -1;
fd = -1;
if (PyLong_Check(result)) {
@ -171,7 +185,7 @@ faulthandler_get_fileno(PyObject *file, int *p_fd)
if (fd == -1) {
PyErr_SetString(PyExc_RuntimeError,
"file.fileno() is not a valid file descriptor");
return NULL;
return -1;
}
result = _PyObject_CallMethodId(file, &PyId_flush, "");
@ -181,8 +195,8 @@ faulthandler_get_fileno(PyObject *file, int *p_fd)
/* ignore flush() error */
PyErr_Clear();
}
*p_fd = fd;
return file;
*file_ptr = file;
return fd;
}
/* Get the state of the current thread: only call this function if the current
@ -215,8 +229,8 @@ faulthandler_dump_traceback_py(PyObject *self,
&file, &all_threads))
return NULL;
file = faulthandler_get_fileno(file, &fd);
if (file == NULL)
fd = faulthandler_get_fileno(&file);
if (fd < 0)
return NULL;
tstate = get_thread_state();
@ -339,8 +353,8 @@ faulthandler_enable(PyObject *self, PyObject *args, PyObject *kwargs)
"|Oi:enable", kwlist, &file, &all_threads))
return NULL;
file = faulthandler_get_fileno(file, &fd);
if (file == NULL)
fd = faulthandler_get_fileno(&file);
if (fd < 0)
return NULL;
tstate = get_thread_state();
@ -348,7 +362,7 @@ faulthandler_enable(PyObject *self, PyObject *args, PyObject *kwargs)
return NULL;
Py_XDECREF(fatal_error.file);
Py_INCREF(file);
Py_XINCREF(file);
fatal_error.file = file;
fatal_error.fd = fd;
fatal_error.all_threads = all_threads;
@ -553,8 +567,8 @@ faulthandler_dump_traceback_later(PyObject *self,
if (tstate == NULL)
return NULL;
file = faulthandler_get_fileno(file, &fd);
if (file == NULL)
fd = faulthandler_get_fileno(&file);
if (fd < 0)
return NULL;
/* format the timeout */
@ -567,7 +581,7 @@ faulthandler_dump_traceback_later(PyObject *self,
cancel_dump_traceback_later();
Py_XDECREF(thread.file);
Py_INCREF(file);
Py_XINCREF(file);
thread.file = file;
thread.fd = fd;
thread.timeout_us = timeout_us;
@ -737,8 +751,8 @@ faulthandler_register_py(PyObject *self,
if (tstate == NULL)
return NULL;
file = faulthandler_get_fileno(file, &fd);
if (file == NULL)
fd = faulthandler_get_fileno(&file);
if (fd < 0)
return NULL;
if (user_signals == NULL) {
@ -760,7 +774,7 @@ faulthandler_register_py(PyObject *self,
}
Py_XDECREF(user->file);
Py_INCREF(file);
Py_XINCREF(file);
user->file = file;
user->fd = fd;
user->all_threads = all_threads;