[pypy-svn] pypy default: kleptog: Support for the PyOS_[gs]etsig functions

amauryfa commits-noreply at bitbucket.org
Thu Mar 10 23:44:48 CET 2011


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: 
Changeset: r42499:538a36110333
Date: 2011-03-10 23:39 +0100
http://bitbucket.org/pypy/pypy/changeset/538a36110333/

Log:	kleptog: Support for the PyOS_[gs]etsig functions

diff --git a/pypy/module/cpyext/src/pysignals.c b/pypy/module/cpyext/src/pysignals.c
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/src/pysignals.c
@@ -0,0 +1,53 @@
+#include <Python.h>
+#include <signal.h>
+
+/* From pythonrun.c in the standard Python distribution */
+
+/* Wrappers around sigaction() or signal(). */
+
+/* It may seem odd that these functions do not interact with the rest of the
+ * system (i.e.  their effects are not visible in the signal module) but
+ * this is apparently intentional, CPython works the same way.  The signal
+ * handlers defined in the signal module define what happens if the normal
+ * Python signal handler is called.
+ *
+ * A bit whacky, but that's the way it is */
+
+PyOS_sighandler_t
+PyOS_getsig(int sig)
+{
+#ifdef SA_RESTART
+        /* assume sigaction exists */
+        struct sigaction context;
+        if (sigaction(sig, NULL, &context) == -1)
+                return SIG_ERR;
+        return context.sa_handler;
+#else
+        PyOS_sighandler_t handler;
+        handler = signal(sig, SIG_IGN);
+        if (handler != SIG_ERR)
+                signal(sig, handler);
+        return handler;
+#endif
+}
+
+PyOS_sighandler_t
+PyOS_setsig(int sig, PyOS_sighandler_t handler)
+{
+#ifdef SA_RESTART
+        /* assume sigaction exists */
+        struct sigaction context, ocontext;
+        context.sa_handler = handler;
+        sigemptyset(&context.sa_mask);
+        context.sa_flags = 0;
+        if (sigaction(sig, &context, &ocontext) == -1)
+                return SIG_ERR;
+        return ocontext.sa_handler;
+#else
+        PyOS_sighandler_t oldhandler;
+        oldhandler = signal(sig, handler);
+        /* should check if this exists */
+        siginterrupt(sig, 1);
+        return oldhandler;
+#endif
+}

diff --git a/pypy/module/cpyext/stubs.py b/pypy/module/cpyext/stubs.py
--- a/pypy/module/cpyext/stubs.py
+++ b/pypy/module/cpyext/stubs.py
@@ -24,7 +24,6 @@
 _inittab = rffi.VOIDP
 PyThreadState = rffi.VOIDP
 PyInterpreterState = rffi.VOIDP
-PyOS_sighandler_t = rffi.VOIDP
 Py_UNICODE = lltype.UniChar
 PyCompilerFlags = rffi.VOIDP
 _node = rffi.VOIDP
@@ -2313,22 +2312,6 @@
     own code."""
     raise NotImplementedError
 
- at cpython_api([rffi.INT_real], PyOS_sighandler_t)
-def PyOS_getsig(space, i):
-    """Return the current signal handler for signal i.  This is a thin wrapper around
-    either sigaction() or signal().  Do not call those functions
-    directly! PyOS_sighandler_t is a typedef alias for void
-    (*)(int)."""
-    raise NotImplementedError
-
- at cpython_api([rffi.INT_real, PyOS_sighandler_t], PyOS_sighandler_t)
-def PyOS_setsig(space, i, h):
-    """Set the signal handler for signal i to be h; return the old signal handler.
-    This is a thin wrapper around either sigaction() or signal().  Do
-    not call those functions directly!  PyOS_sighandler_t is a typedef
-    alias for void (*)(int)."""
-    raise NotImplementedError
-
 @cpython_api([rffi.CCHARP, FILE], FILE)
 def PySys_GetFile(space, name, default):
     """Return the FILE* associated with the object name in the

diff --git a/pypy/module/cpyext/include/pysignals.h b/pypy/module/cpyext/include/pysignals.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/include/pysignals.h
@@ -0,0 +1,19 @@
+
+/* signal interface */
+
+#ifndef Py_PYSIGNALS_H
+#define Py_PYSIGNALS_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void (*PyOS_sighandler_t)(int);
+
+PyOS_sighandler_t PyOS_setsig(int sig, PyOS_sighandler_t handler);
+PyOS_sighandler_t PyOS_getsig(int sig);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_PYSIGNALS_H */

diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -331,6 +331,8 @@
     'PyCapsule_SetContext', 'PyCapsule_Import', 'PyCapsule_Type', 'init_capsule',
 
     'PyObject_AsReadBuffer', 'PyObject_AsWriteBuffer', 'PyObject_CheckReadBuffer',
+    
+    'PyOS_getsig', 'PyOS_setsig',
 
     'PyStructSequence_InitType', 'PyStructSequence_New',
 ]
@@ -886,6 +888,7 @@
                                source_dir / "cobject.c",
                                source_dir / "structseq.c",
                                source_dir / "capsule.c",
+                               source_dir / "pysignals.c",
                                ],
         separate_module_sources=separate_module_sources,
         export_symbols=export_symbols_eci,

diff --git a/pypy/module/cpyext/include/Python.h b/pypy/module/cpyext/include/Python.h
--- a/pypy/module/cpyext/include/Python.h
+++ b/pypy/module/cpyext/include/Python.h
@@ -118,6 +118,7 @@
 #include "datetime.h"
 #include "pystate.h"
 #include "fileobject.h"
+#include "pysignals.h"
 
 // XXX This shouldn't be included here
 #include "structmember.h"

diff --git a/pypy/module/cpyext/test/test_pysignals.py b/pypy/module/cpyext/test/test_pysignals.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/test/test_pysignals.py
@@ -0,0 +1,30 @@
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+
+class AppTestBufferObject(AppTestCpythonExtensionBase):
+    def test_signals(self):
+        module = self.import_extension('foo', [
+            ("test_signals", "METH_NOARGS",
+             """
+                 PyOS_sighandler_t handler = SIG_IGN;
+                 PyOS_sighandler_t oldhandler;
+                 int result = 0;
+                 
+                 oldhandler = PyOS_getsig(SIGUSR1);
+                 
+                 handler = PyOS_setsig(SIGUSR1, SIG_IGN);
+                 
+                 if( oldhandler != handler )
+                     result += 1;
+                 
+                 handler = PyOS_setsig(SIGUSR1, oldhandler);
+                 
+                 if( handler != SIG_IGN )
+                     result += 2;
+                 
+                 return PyInt_FromLong(result);
+             """),
+            ], prologue = """
+            #include <signal.h>
+            """)
+        res = module.test_signals()
+        assert res == 0


More information about the Pypy-commit mailing list