bpo-30125: Fix faulthandler.disable() on Windows (#1240)
* bpo-30125: Cleanup faulthandler.c * Use size_t type for iterators * Add { ... } * bpo-30125: Fix faulthandler.disable() on Windows On Windows, faulthandler.disable() now removes the exception handler installed by faulthandler.enable().
This commit is contained in:
parent
2a1aed04b0
commit
46c2b81026
@ -754,6 +754,18 @@ class FaultHandlerTests(unittest.TestCase):
|
|||||||
3,
|
3,
|
||||||
name)
|
name)
|
||||||
|
|
||||||
|
@unittest.skipUnless(MS_WINDOWS, 'specific to Windows')
|
||||||
|
def test_disable_windows_exc_handler(self):
|
||||||
|
code = dedent("""
|
||||||
|
import faulthandler
|
||||||
|
faulthandler.enable()
|
||||||
|
faulthandler.disable()
|
||||||
|
code = faulthandler._EXCEPTION_ACCESS_VIOLATION
|
||||||
|
faulthandler._raise_exception(code)
|
||||||
|
""")
|
||||||
|
output, exitcode = self.get_output(code)
|
||||||
|
self.assertEqual(output, [])
|
||||||
|
self.assertEqual(exitcode, 0xC0000005)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@ -55,6 +55,9 @@ static struct {
|
|||||||
int fd;
|
int fd;
|
||||||
int all_threads;
|
int all_threads;
|
||||||
PyInterpreterState *interp;
|
PyInterpreterState *interp;
|
||||||
|
#ifdef MS_WINDOWS
|
||||||
|
void *exc_handler;
|
||||||
|
#endif
|
||||||
} fatal_error = {0, NULL, -1, 0};
|
} fatal_error = {0, NULL, -1, 0};
|
||||||
|
|
||||||
#ifdef FAULTHANDLER_LATER
|
#ifdef FAULTHANDLER_LATER
|
||||||
@ -395,8 +398,7 @@ faulthandler_exc_handler(struct _EXCEPTION_POINTERS *exc_info)
|
|||||||
|
|
||||||
if (code == EXCEPTION_ACCESS_VIOLATION) {
|
if (code == EXCEPTION_ACCESS_VIOLATION) {
|
||||||
/* disable signal handler for SIGSEGV */
|
/* disable signal handler for SIGSEGV */
|
||||||
size_t i;
|
for (size_t i=0; i < faulthandler_nsignals; i++) {
|
||||||
for (i=0; i < faulthandler_nsignals; i++) {
|
|
||||||
fault_handler_t *handler = &faulthandler_handlers[i];
|
fault_handler_t *handler = &faulthandler_handlers[i];
|
||||||
if (handler->signum == SIGSEGV) {
|
if (handler->signum == SIGSEGV) {
|
||||||
faulthandler_disable_fatal_handler(handler);
|
faulthandler_disable_fatal_handler(handler);
|
||||||
@ -418,14 +420,12 @@ faulthandler_exc_handler(struct _EXCEPTION_POINTERS *exc_info)
|
|||||||
static int
|
static int
|
||||||
faulthandler_enable(void)
|
faulthandler_enable(void)
|
||||||
{
|
{
|
||||||
size_t i;
|
|
||||||
|
|
||||||
if (fatal_error.enabled) {
|
if (fatal_error.enabled) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
fatal_error.enabled = 1;
|
fatal_error.enabled = 1;
|
||||||
|
|
||||||
for (i=0; i < faulthandler_nsignals; i++) {
|
for (size_t i=0; i < faulthandler_nsignals; i++) {
|
||||||
fault_handler_t *handler;
|
fault_handler_t *handler;
|
||||||
#ifdef HAVE_SIGACTION
|
#ifdef HAVE_SIGACTION
|
||||||
struct sigaction action;
|
struct sigaction action;
|
||||||
@ -462,7 +462,8 @@ faulthandler_enable(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
AddVectoredExceptionHandler(1, faulthandler_exc_handler);
|
assert(fatal_error.exc_handler == NULL);
|
||||||
|
fatal_error.exc_handler = AddVectoredExceptionHandler(1, faulthandler_exc_handler);
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -504,17 +505,20 @@ faulthandler_py_enable(PyObject *self, PyObject *args, PyObject *kwargs)
|
|||||||
static void
|
static void
|
||||||
faulthandler_disable(void)
|
faulthandler_disable(void)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
|
||||||
fault_handler_t *handler;
|
|
||||||
|
|
||||||
if (fatal_error.enabled) {
|
if (fatal_error.enabled) {
|
||||||
fatal_error.enabled = 0;
|
fatal_error.enabled = 0;
|
||||||
for (i=0; i < faulthandler_nsignals; i++) {
|
for (size_t i=0; i < faulthandler_nsignals; i++) {
|
||||||
|
fault_handler_t *handler;
|
||||||
handler = &faulthandler_handlers[i];
|
handler = &faulthandler_handlers[i];
|
||||||
faulthandler_disable_fatal_handler(handler);
|
faulthandler_disable_fatal_handler(handler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef MS_WINDOWS
|
||||||
|
if (fatal_error.exc_handler != NULL) {
|
||||||
|
RemoveVectoredExceptionHandler(fatal_error.exc_handler);
|
||||||
|
fatal_error.exc_handler = NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
Py_CLEAR(fatal_error.file);
|
Py_CLEAR(fatal_error.file);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -777,9 +781,7 @@ faulthandler_user(int signum)
|
|||||||
static int
|
static int
|
||||||
check_signum(int signum)
|
check_signum(int signum)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
for (size_t i=0; i < faulthandler_nsignals; i++) {
|
||||||
|
|
||||||
for (i=0; i < faulthandler_nsignals; i++) {
|
|
||||||
if (faulthandler_handlers[i].signum == signum) {
|
if (faulthandler_handlers[i].signum == signum) {
|
||||||
PyErr_Format(PyExc_RuntimeError,
|
PyErr_Format(PyExc_RuntimeError,
|
||||||
"signal %i cannot be registered, "
|
"signal %i cannot be registered, "
|
||||||
@ -1122,16 +1124,12 @@ faulthandler_stack_overflow(PyObject *self)
|
|||||||
static int
|
static int
|
||||||
faulthandler_traverse(PyObject *module, visitproc visit, void *arg)
|
faulthandler_traverse(PyObject *module, visitproc visit, void *arg)
|
||||||
{
|
{
|
||||||
#ifdef FAULTHANDLER_USER
|
|
||||||
unsigned int signum;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef FAULTHANDLER_LATER
|
#ifdef FAULTHANDLER_LATER
|
||||||
Py_VISIT(thread.file);
|
Py_VISIT(thread.file);
|
||||||
#endif
|
#endif
|
||||||
#ifdef FAULTHANDLER_USER
|
#ifdef FAULTHANDLER_USER
|
||||||
if (user_signals != NULL) {
|
if (user_signals != NULL) {
|
||||||
for (signum=0; signum < NSIG; signum++)
|
for (size_t signum=0; signum < NSIG; signum++)
|
||||||
Py_VISIT(user_signals[signum].file);
|
Py_VISIT(user_signals[signum].file);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1342,10 +1340,6 @@ int _PyFaulthandler_Init(void)
|
|||||||
|
|
||||||
void _PyFaulthandler_Fini(void)
|
void _PyFaulthandler_Fini(void)
|
||||||
{
|
{
|
||||||
#ifdef FAULTHANDLER_USER
|
|
||||||
unsigned int signum;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef FAULTHANDLER_LATER
|
#ifdef FAULTHANDLER_LATER
|
||||||
/* later */
|
/* later */
|
||||||
if (thread.cancel_event) {
|
if (thread.cancel_event) {
|
||||||
@ -1363,8 +1357,9 @@ void _PyFaulthandler_Fini(void)
|
|||||||
#ifdef FAULTHANDLER_USER
|
#ifdef FAULTHANDLER_USER
|
||||||
/* user */
|
/* user */
|
||||||
if (user_signals != NULL) {
|
if (user_signals != NULL) {
|
||||||
for (signum=0; signum < NSIG; signum++)
|
for (size_t signum=0; signum < NSIG; signum++) {
|
||||||
faulthandler_unregister(&user_signals[signum], signum);
|
faulthandler_unregister(&user_signals[signum], signum);
|
||||||
|
}
|
||||||
PyMem_Free(user_signals);
|
PyMem_Free(user_signals);
|
||||||
user_signals = NULL;
|
user_signals = NULL;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user