[Python-checkins] r60983 - in python/trunk: Doc/library/signal.rst Lib/test/test_signal.py Misc/NEWS Modules/signalmodule.c

facundo.batista python-checkins at python.org
Sat Feb 23 16:07:36 CET 2008


Author: facundo.batista
Date: Sat Feb 23 16:07:35 2008
New Revision: 60983

Modified:
   python/trunk/Doc/library/signal.rst
   python/trunk/Lib/test/test_signal.py
   python/trunk/Misc/NEWS
   python/trunk/Modules/signalmodule.c
Log:

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.


Modified: python/trunk/Doc/library/signal.rst
==============================================================================
--- python/trunk/Doc/library/signal.rst	(original)
+++ python/trunk/Doc/library/signal.rst	Sat Feb 23 16:07:35 2008
@@ -124,6 +124,21 @@
    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

Modified: python/trunk/Lib/test/test_signal.py
==============================================================================
--- python/trunk/Lib/test/test_signal.py	(original)
+++ python/trunk/Lib/test/test_signal.py	Sat Feb 23 16:07:35 2008
@@ -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 @@
         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 @@
                                        sys.platform)
 
     test_support.run_unittest(BasicSignalTests, InterProcessSignalTests,
-        WakeupSignalTests)
+        WakeupSignalTests, SiginterruptTest)
 
 
 if __name__ == "__main__":

Modified: python/trunk/Misc/NEWS
==============================================================================
--- python/trunk/Misc/NEWS	(original)
+++ python/trunk/Misc/NEWS	Sat Feb 23 16:07:35 2008
@@ -1186,6 +1186,7 @@
   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
 -----------------

Modified: python/trunk/Modules/signalmodule.c
==============================================================================
--- python/trunk/Modules/signalmodule.c	(original)
+++ python/trunk/Modules/signalmodule.c	Sat Feb 23 16:07:35 2008
@@ -272,6 +272,36 @@
 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 @@
 	{"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},


More information about the Python-checkins mailing list