Commit 7e251e83 authored by Facundo Batista's avatar Facundo Batista

Issue 1089358. Adds the siginterrupt() function, that is just a

wrapper around the system call with the same name.  Also added
test cases, doc changes and NEWS entry. Thanks Jason and Ralf
Schmitt.
parent 57826cf9
......@@ -124,6 +124,21 @@ The :mod:`signal` module defines the following functions:
exception to be raised.
.. function:: siginterrupt(signalnum, flag)
Change system call restart behaviour: if *flag* is :const:`False`, system calls
will be restarted when interrupted by signal *signalnum*, else system calls will
be interrupted. Returns nothing. Availability: Unix, Mac (see the man page
:manpage:`siginterrupt(3)` for further information).
Note that installing a signal handler with :func:`signal` will reset the restart
behaviour to interruptible by implicitly calling siginterrupt with a true *flag*
value for the given signal.
.. versionadded:: 2.6
.. function:: signal(signalnum, handler)
Set the handler for signal *signalnum* to the function *handler*. *handler* can
......
import unittest
from test import test_support
import signal
import os, sys, time
import os, sys, time, errno
class HandlerBCalled(Exception):
pass
......@@ -210,6 +210,50 @@ class WakeupSignalTests(unittest.TestCase):
os.close(self.write)
signal.signal(signal.SIGALRM, self.alrm)
class SiginterruptTest(unittest.TestCase):
signum = signal.SIGUSR1
def readpipe_interrupted(self, cb):
r, w = os.pipe()
ppid = os.getpid()
pid = os.fork()
oldhandler = signal.signal(self.signum, lambda x,y: None)
cb()
if pid==0:
# child code: sleep, kill, sleep. and then exit,
# which closes the pipe from which the parent process reads
try:
time.sleep(0.2)
os.kill(ppid, self.signum)
time.sleep(0.2)
finally:
os._exit(0)
try:
os.close(w)
try:
d=os.read(r, 1)
return False
except OSError, err:
if err.errno != errno.EINTR:
raise
return True
finally:
signal.signal(self.signum, oldhandler)
os.waitpid(pid, 0)
def test_without_siginterrupt(self):
i=self.readpipe_interrupted(lambda: None)
self.assertEquals(i, True)
def test_siginterrupt_on(self):
i=self.readpipe_interrupted(lambda: signal.siginterrupt(self.signum, 1))
self.assertEquals(i, True)
def test_siginterrupt_off(self):
i=self.readpipe_interrupted(lambda: signal.siginterrupt(self.signum, 0))
self.assertEquals(i, False)
def test_main():
if sys.platform[:3] in ('win', 'os2') or sys.platform == 'riscos':
......@@ -217,7 +261,7 @@ def test_main():
sys.platform)
test_support.run_unittest(BasicSignalTests, InterProcessSignalTests,
WakeupSignalTests)
WakeupSignalTests, SiginterruptTest)
if __name__ == "__main__":
......
......@@ -1186,6 +1186,7 @@ Library
does not claim to support starttls. Adds the SMTP.ehlo_or_helo_if_needed()
method. Patch contributed by Bill Fenner.
- Patch #1089358: Add signal.siginterrupt, a wrapper around siginterrupt(3).
Extension Modules
-----------------
......
......@@ -272,6 +272,36 @@ 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_SIGINTERRUPT
PyDoc_STRVAR(siginterrupt_doc,
"siginterrupt(sig, flag) -> None\n\
change system call restart behaviour: if flag is False, system calls\n\
will be restarted when interrupted by signal sig, else system calls\n\
will be interrupted.");
static PyObject *
signal_siginterrupt(PyObject *self, PyObject *args)
{
int sig_num;
int flag;
if (!PyArg_ParseTuple(args, "ii:siginterrupt", &sig_num, &flag))
return NULL;
if (sig_num < 1 || sig_num >= NSIG) {
PyErr_SetString(PyExc_ValueError,
"signal number out of range");
return NULL;
}
if (siginterrupt(sig_num, flag)<0) {
PyErr_SetFromErrno(PyExc_RuntimeError);
return NULL;
}
Py_INCREF(Py_None);
return Py_None;
}
#endif
static PyObject *
signal_set_wakeup_fd(PyObject *self, PyObject *args)
......@@ -325,6 +355,9 @@ static PyMethodDef signal_methods[] = {
{"signal", signal_signal, METH_VARARGS, signal_doc},
{"getsignal", signal_getsignal, METH_VARARGS, getsignal_doc},
{"set_wakeup_fd", signal_set_wakeup_fd, METH_VARARGS, set_wakeup_fd_doc},
#ifdef HAVE_SIGINTERRUPT
{"siginterrupt", signal_siginterrupt, METH_VARARGS, siginterrupt_doc},
#endif
#ifdef HAVE_PAUSE
{"pause", (PyCFunction)signal_pause,
METH_NOARGS,pause_doc},
......
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