2 * Copyright (c) 2010 Twisted Matrix Laboratories.
3 * See LICENSE for details.
11 static int sigchld_pipe_fd = -1;
13 static void got_signal(int sig) {
14 int saved_errno = errno;
17 /* write() errors are unhandled. If the buffer is full, we don't
18 * care. What about other errors? */
19 ignored_result = write(sigchld_pipe_fd, "x", 1);
24 PyDoc_STRVAR(install_sigchld_handler_doc, "\
25 install_sigchld_handler(fd)\n\
27 Installs a SIGCHLD handler which will write a byte to the given fd\n\
28 whenever a SIGCHLD occurs. This is done in C code because the python\n\
29 signal handling system is not reliable, and additionally cannot\n\
30 specify SA_RESTART.\n\
32 Please ensure fd is in non-blocking mode.\n\
36 install_sigchld_handler(PyObject *self, PyObject *args) {
40 if (!PyArg_ParseTuple(args, "i:install_sigchld_handler", &fd)) {
43 old_fd = sigchld_pipe_fd;
47 sa.sa_handler = SIG_DFL;
49 sa.sa_handler = got_signal;
50 sa.sa_flags = SA_RESTART;
51 /* mask all signals so I don't worry about EINTR from the write. */
52 sigfillset(&sa.sa_mask);
54 if (sigaction(SIGCHLD, &sa, 0) != 0) {
55 sigchld_pipe_fd = old_fd;
56 return PyErr_SetFromErrno(PyExc_OSError);
58 return PyLong_FromLong(old_fd);
61 PyDoc_STRVAR(is_default_handler_doc, "\
62 Return 1 if the SIGCHLD handler is SIG_DFL, 0 otherwise.\n\
66 is_default_handler(PyObject *self, PyObject *args) {
68 * This implementation is necessary since the install_sigchld_handler
69 * function above bypasses the Python signal handler installation API, so
70 * CPython doesn't notice that the handler has changed and signal.getsignal
71 * won't return an accurate result.
75 if (sigaction(SIGCHLD, NULL, &sa) != 0) {
76 return PyErr_SetFromErrno(PyExc_OSError);
79 return PyLong_FromLong(sa.sa_handler == SIG_DFL);
82 static PyMethodDef sigchld_methods[] = {
83 {"installHandler", install_sigchld_handler, METH_VARARGS,
84 install_sigchld_handler_doc},
85 {"isDefaultHandler", is_default_handler, METH_NOARGS,
86 is_default_handler_doc},
92 static const char _sigchld_doc[] = "\n\
93 This module contains an API for receiving SIGCHLD via a file descriptor.\n\
98 /* Create the module and add the functions */
100 "twisted.internet._sigchld", sigchld_methods, _sigchld_doc);