diff options
author | Facundo Batista <facundobatista@gmail.com> | 2008-02-23 15:07:35 (GMT) |
---|---|---|
committer | Facundo Batista <facundobatista@gmail.com> | 2008-02-23 15:07:35 (GMT) |
commit | 7e251e83d5b488904212f91bace1322d12475803 (patch) | |
tree | 29f24e91e6a5261772816d5b500937b59e9a819d | |
parent | 57826cf9f8c1d75da8d7d0e27f564adb441329ad (diff) | |
download | cpython-7e251e83d5b488904212f91bace1322d12475803.zip cpython-7e251e83d5b488904212f91bace1322d12475803.tar.gz cpython-7e251e83d5b488904212f91bace1322d12475803.tar.bz2 |
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.
-rw-r--r-- | Doc/library/signal.rst | 15 | ||||
-rw-r--r-- | Lib/test/test_signal.py | 48 | ||||
-rw-r--r-- | Misc/NEWS | 1 | ||||
-rw-r--r-- | Modules/signalmodule.c | 33 |
4 files changed, 95 insertions, 2 deletions
diff --git a/Doc/library/signal.rst b/Doc/library/signal.rst index afb3166..7fe7ec1 100644 --- a/Doc/library/signal.rst +++ b/Doc/library/signal.rst @@ -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 diff --git a/Lib/test/test_signal.py b/Lib/test/test_signal.py index 8cf82f4..332001f 100644 --- a/Lib/test/test_signal.py +++ b/Lib/test/test_signal.py @@ -1,7 +1,7 @@ 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 ----------------- diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c index 9dec24f..8acec21 100644 --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -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}, |