Commit 43ed43bf authored by Michael W. Hudson's avatar Michael W. Hudson

Take out my (long since disabled) POSIX signal mask handling code.

I'm not going to have the time or energy to get this working x-platform
-- anyone who does is welcome to the code!
parent 94afd309
......@@ -17,6 +17,10 @@ regardless of the underlying implementation), with the exception of
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
......@@ -88,16 +92,6 @@ The variables defined in the \module{signal} module are:
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}
......@@ -150,46 +144,6 @@ The \module{signal} module defines the following functions:
\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}
......
......@@ -1485,10 +1485,8 @@ it immediately.)
location.
\item Support for more advanced POSIX signal handling was added
to the \module{signal} module by adding the \function{sigpending},
\function{sigprocmask} and \function{sigsuspend} functions where supported
by the platform. These functions make it possible to avoid some previously
unavoidable race conditions with signal handling.
to the \module{signal} but then removed again as it proved impossible
to make it work reliably across platforms.
\item The \module{socket} module now supports timeouts. You
can call the \method{settimeout(\var{t})} method on a socket object to
......
......@@ -64,64 +64,3 @@ except KeyboardInterrupt:
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"
......@@ -982,9 +982,6 @@ Extension modules
of sizeof(int)!=sizeof(long)!=sizeof(void*) is delayed until dl.open
is called.
- signal.sigpending, signal.sigprocmask and signal.sigsuspend have
been added where available.
- The sys module acquired a new attribute, api_version, which evaluates
to the value of the PYTHON_API_VERSION macro with which the
interpreter was compiled.
......
......@@ -269,153 +269,6 @@ SIG_DFL -- if the default action for the signal is in effect\n\
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[] = {
......@@ -430,14 +283,6 @@ 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 */
};
......@@ -453,10 +298,6 @@ getsignal() -- get the signal action for a given signal\n\
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\
......@@ -705,18 +546,6 @@ initsignal(void)
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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment