the handler for \constant{SIGCHLD}, which follows the underlying
implementation.
+\item
+There is no way to ``block'' signals temporarily from critical
+sections (since this is not supported by all \UNIX{} flavors).
+
\item
Although Python signal handlers are called asynchronously as far as
the Python user is concerned, they can only occur between the
One more than the number of the highest signal number.
\end{datadesc}
-\begin{datadesc}{SIG_BLOCK}
-\end{datadesc}
-\begin{datadesc}{SIG_UNBLOCK}
-\end{datadesc}
-\begin{datadesc}{SIG_SETMASK}
- These constants are for use as the first parameter of the
- \function{sigprocmask} function described below.
-\end{datadesc}
-
-
The \module{signal} module defines the following functions:
\begin{funcdesc}{alarm}{time}
\obindex{frame}
\end{funcdesc}
-The following functions are supported if your platform does. Most
-modern \UNIX-alikes now do.
-
-\begin{funcdesc}{sigpending}{}
- Return the set of pending signals, i.e. a list containing the
- numbers of those signals that have been raised while blocked.
- \versionadded{2.3}
-\end{funcdesc}
-
-\begin{funcdesc}{sigprocmask}{how, sigset}
- Change the list of currently blocked signals. The parameter
- \var{how} should be one of \constant{SIG_BLOCK},
- \constant{SIG_UNBLOCK} or \constant{SIG_SETMASK} and \var{sigset}
- should be a sequence of signal numbers. The behaviour of the call
- depends on the value of \var{how}:
-
- \begin{tableii}{l|l}{textrm}{Value of \var{how}}{Behaviour of call}
- \lineii{\constant{SIG_BLOCK}}
- {The set of blocked signals is the union of the current set
- and \var{sigset}.}
- \lineii{\constant{SIG_UNBLOCK}}
- {The signals in \var{sigset} are removed from the current
- set of blocked signals. It is legal to attempt to unblock
- a signal which is not blocked.}
- \lineii{\constant{SIG_SETMASK}}
- {The set of blocked signals is set to the \var{sigset}.}
- \end{tableii}
-
- A list contating the numbers of the previously blocked signals is
- returned.
- \versionadded{2.3}
-\end{funcdesc}
-
-\begin{funcdesc}{sigsuspend}{sigset}
- Temporarily replace the signal mask with \var{sigset} (which should
- be a sequnce of signal numbers) and suspend the process until a
- signal is received.
- \versionadded{2.3}
-\end{funcdesc}
-
\subsection{Example}
\nodename{Signal Example}
if verbose:
print "KeyboardInterrupt (assume the alarm() went off)"
-
-if hasattr(signal, "sigprocmask"):
- class HupDelivered(Exception):
- pass
- def hup(signum, frame):
- raise HupDelivered
- def hup2(signum, frame):
- signal.signal(signal.SIGHUP, hup)
- return
- signal.signal(signal.SIGHUP, hup)
-
- if verbose:
- print "blocking SIGHUP"
-
- defaultmask = signal.sigprocmask(signal.SIG_BLOCK, [signal.SIGHUP])
-
- if verbose:
- print "sending SIGHUP"
-
- try:
- os.kill(pid, signal.SIGHUP)
- except HupDelivered:
- raise TestFailed, "HUP not blocked"
-
- if signal.SIGHUP not in signal.sigpending():
- raise TestFailed, "HUP not pending"
-
- if verbose:
- print "unblocking SIGHUP"
-
- try:
- signal.sigprocmask(signal.SIG_UNBLOCK, [signal.SIGHUP])
- except HupDelivered:
- pass
- else:
- raise TestFailed, "HUP not delivered"
-
- if verbose:
- print "testing sigsuspend"
-
- signal.sigprocmask(signal.SIG_BLOCK, [signal.SIGHUP])
- signal.signal(signal.SIGHUP, hup2)
-
- if not os.fork():
- time.sleep(2)
- os.kill(pid, signal.SIGHUP)
- time.sleep(2)
- os.kill(pid, signal.SIGHUP)
- os._exit(0)
- else:
- try:
- signal.sigsuspend(defaultmask)
- except:
- raise TestFailed, "sigsuspend erroneously raised"
-
- try:
- signal.sigsuspend(defaultmask)
- except HupDelivered:
- pass
- else:
- raise TestFailed, "sigsupsend didn't raise"
None -- if an unknown handler is in effect\n\
anything else -- the callable Python object used as a handler");
-#ifdef HAVE_SIGPROCMASK /* we assume that having SIGPROCMASK is enough
- to guarantee full POSIX signal handling */
-/* returns 0 for success, <0 for failure (with exception set) */
-static int
-_signal_list_to_sigset(PyObject* seq, sigset_t* set, char* mesg)
-{
- int i, len, val;
-
- seq = PySequence_Fast(seq, mesg);
- if (!seq)
- return -1;
-
- len = PySequence_Fast_GET_SIZE(seq);
-
- sigemptyset(set);
-
- for (i = 0; i < len; i++) {
- val = PyInt_AsLong(PySequence_Fast_GET_ITEM(seq, i));
- if (val == -1 && PyErr_Occurred()) {
- Py_DECREF(seq);
- return -1;
- }
- if (sigaddset(set, val) < 0) {
- Py_DECREF(seq);
- PyErr_SetFromErrno(PyExc_ValueError);
- return -1;
- }
- }
-
- Py_DECREF(seq);
- return 0;
-}
-
-static PyObject*
-_signal_sigset_to_list(sigset_t* set)
-{
- PyObject* ret;
- PyObject* ob;
- int i;
-
- ret = PyList_New(0);
- if (!ret)
- return NULL;
-
- for (i = 1; i < NSIG; i++) {
- if (sigismember(set, i)) {
- ob = PyInt_FromLong(i);
- if (!ob) {
- Py_DECREF(ret);
- return NULL;
- }
- PyList_Append(ret, ob);
- Py_DECREF(ob);
- }
- }
-
- return ret;
-}
-
-static PyObject*
-signal_sigprocmask(PyObject* self, PyObject* args)
-{
- int how;
- sigset_t newset, oldset;
- PyObject* seq;
-
- if (!PyArg_ParseTuple(args, "iO", &how, &seq))
- return NULL;
-
- if (_signal_list_to_sigset(seq, &newset,
- "sigprocmask requires a sequence") < 0)
- return NULL;
-
- if (sigprocmask(how, &newset, &oldset) < 0) {
- return PyErr_SetFromErrno(PyExc_ValueError);
- }
-
- if (PyErr_CheckSignals())
- return NULL;
-
- return _signal_sigset_to_list(&oldset);
-}
-
-PyDoc_STRVAR(sigprocmask_doc,
-"sigprocmask(how, sigset) -> sigset\n\
-\n\
-Change the list of currently blocked signals. The parameter how should be\n\
-one of SIG_BLOCK, SIG_UNBLOCK or SIG_SETMASK and sigset should be a\n\
-sequence of signal numbers. The behaviour of the call depends on the value\n\
-of how:\n\
-\n\
- SIG_BLOCK\n\
- The set of blocked signals is the union of the current set and the\n\
- sigset argument.\n\
- SIG_UNBLOCK\n\
- The signals in sigset are removed from the current set of blocked\n\
- signals. It is legal to attempt to unblock a signal which is not\n\
- blocked.\n\
- SIG_SETMASK\n\
- The set of blocked signals is set to the argument set.\n\
-\n\
-A list contating the numbers of the previously blocked signals is returned.");
-
-static PyObject*
-signal_sigpending(PyObject* self)
-{
- sigset_t set;
-
- if (sigpending(&set) < 0) {
- return PyErr_SetFromErrno(PyExc_ValueError);
- }
-
- return _signal_sigset_to_list(&set);
-}
-
-PyDoc_STRVAR(sigpending_doc,
-"sigpending() -> sigset\n\
-\n\
-Return the set of pending signals, i.e. a list containing the numbers of\n\
-those signals that have been raised while blocked.");
-
-static PyObject*
-signal_sigsuspend(PyObject* self, PyObject* arg)
-{
- sigset_t set;
-
- if (_signal_list_to_sigset(arg, &set,
- "sigsuspend requires a sequence") < 0)
- return NULL;
-
- Py_BEGIN_ALLOW_THREADS
- sigsuspend(&set);
- Py_END_ALLOW_THREADS
-
- if (PyErr_CheckSignals())
- return NULL;
-
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-PyDoc_STRVAR(sigsuspend_doc,
-"sigsuspend(sigset) -> None\n\
-\n\
-Temporarily replace the signal mask with sigset (which should be a sequence\n\
-of signal numbers) and suspend the process until a signal is received.");
-#endif
/* List of functions defined in the module */
static PyMethodDef signal_methods[] = {
#endif
{"default_int_handler", signal_default_int_handler,
METH_VARARGS, default_int_handler_doc},
-#ifdef HAVE_SIGPROCMASK
- {"sigprocmask", (PyCFunction)signal_sigprocmask,
- METH_VARARGS, sigprocmask_doc},
- {"sigpending", (PyCFunction)signal_sigpending,
- METH_NOARGS, sigpending_doc},
- {"sigsuspend", (PyCFunction)signal_sigsuspend,
- METH_O, sigsuspend_doc},
-#endif
{NULL, NULL} /* sentinel */
};
pause() -- wait until a signal arrives [Unix only]\n\
default_int_handler() -- default SIGINT handler\n\
\n\
-sigpending() |\n\
-sigprocmask() |-- posix signal mask handling [Unix only]\n\
-sigsuspend() |\n\
-\n\
Constants:\n\
\n\
SIG_DFL -- used to refer to the system default handler\n\
PyDict_SetItemString(d, "SIGINFO", x);
Py_XDECREF(x);
#endif
-#ifdef HAVE_SIGPROCMASK
- x = PyInt_FromLong(SIG_BLOCK);
- PyDict_SetItemString(d, "SIG_BLOCK", x);
- Py_XDECREF(x);
- x = PyInt_FromLong(SIG_UNBLOCK);
- PyDict_SetItemString(d, "SIG_UNBLOCK", x);
- Py_XDECREF(x);
- x = PyInt_FromLong(SIG_SETMASK);
- PyDict_SetItemString(d, "SIG_SETMASK", x);
- Py_XDECREF(x);
-#endif
-
if (!PyErr_Occurred())
return;