static PyObject* faulthandler_register_py(PyObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"signum", "file", "all_threads", "chain", NULL}; int signum; PyObject *file = NULL; int all_threads = 1; int chain = 0; int fd; user_signal_t *user; _Py_sighandler_t previous; PyThreadState *tstate; int err; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|Oii:register", kwlist, &signum, &file, &all_threads, &chain)) return NULL; if (!check_signum(signum)) return NULL; tstate = get_thread_state(); if (tstate == NULL) return NULL; file = faulthandler_get_fileno(file, &fd); if (file == NULL) return NULL; if (user_signals == NULL) { user_signals = PyMem_Malloc(NSIG * sizeof(user_signal_t)); if (user_signals == NULL) return PyErr_NoMemory(); memset(user_signals, 0, NSIG * sizeof(user_signal_t)); } user = &user_signals[signum]; if (!user->enabled) { err = faulthandler_register(signum, chain, &previous); if (err) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } user->previous = previous; } Py_XDECREF(user->file); Py_INCREF(file); user->file = file; user->fd = fd; user->all_threads = all_threads; user->chain = chain; user->interp = tstate->interp; user->enabled = 1; Py_RETURN_NONE; }
int sigchain_pop(int sig) { struct sigchain_signal *s = signals + sig; check_signum(sig); if (s->n < 1) return 0; if (signal(sig, s->old[s->n - 1]) == SIG_ERR) return -1; s->n--; return 0; }
static int sigchain_push(int sig, sigchain_fun f) { struct sigchain_signal *s = signals + sig; check_signum(sig); ALLOC_GROW(s->old, s->n + 1, s->alloc); s->old[s->n] = signal(sig, f); if (s->old[s->n] == SIG_ERR) return -1; s->n++; return 0; }
static PyObject* faulthandler_unregister_py(PyObject *self, PyObject *args) { int signum; user_signal_t *user; int change; if (!PyArg_ParseTuple(args, "i:unregister", &signum)) return NULL; if (!check_signum(signum)) return NULL; user = &user_signals[signum]; change = faulthandler_unregister(user, signum); return PyBool_FromLong(change); }
static PyObject* faulthandler_register(PyObject *self, PyObject *args, PyObject *kwargs) { static char *kwlist[] = {"signum", "file", "all_threads", NULL}; int signum; PyObject *file = NULL; int all_threads = 0; int fd; user_signal_t *user; _Py_sighandler_t previous; #ifdef HAVE_SIGACTION struct sigaction action; #endif PyThreadState *tstate; int err; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|Oi:register", kwlist, &signum, &file, &all_threads)) return NULL; if (!check_signum(signum)) return NULL; /* The caller holds the GIL and so PyThreadState_Get() can be used */ tstate = PyThreadState_Get(); if (tstate == NULL) { PyErr_SetString(PyExc_RuntimeError, "unable to get the current thread state"); return NULL; } file = faulthandler_get_fileno(file, &fd); if (file == NULL) return NULL; if (user_signals == NULL) { user_signals = calloc(NSIG, sizeof(user_signal_t)); if (user_signals == NULL) return PyErr_NoMemory(); } user = &user_signals[signum]; if (!user->enabled) { #ifdef HAVE_SIGACTION action.sa_handler = faulthandler_user; sigemptyset(&action.sa_mask); /* if the signal is received while the kernel is executing a system call, try to restart the system call instead of interrupting it and return EINTR */ action.sa_flags = SA_RESTART; #ifdef HAVE_SIGALTSTACK if (stack.ss_sp != NULL) { /* Call the signal handler on an alternate signal stack provided by sigaltstack() */ action.sa_flags |= SA_ONSTACK; } #endif err = sigaction(signum, &action, &previous); #else previous = signal(signum, faulthandler_user); err = (previous == SIG_ERR); #endif if (err) { PyErr_SetFromErrno(PyExc_OSError); return NULL; } } Py_XDECREF(user->file); Py_INCREF(file); user->file = file; user->fd = fd; user->all_threads = all_threads; user->previous = previous; user->interp = tstate->interp; user->enabled = 1; Py_RETURN_NONE; }