[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