[pypy-commit] pypy py3.3: Add signal.sigwait()

amauryfa noreply at buildbot.pypy.org
Sun Jan 4 19:14:12 CET 2015


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: py3.3
Changeset: r75230:385525065b2d
Date: 2015-01-04 14:29 +0100
http://bitbucket.org/pypy/pypy/changeset/385525065b2d/

Log:	Add signal.sigwait()

diff --git a/pypy/module/signal/__init__.py b/pypy/module/signal/__init__.py
--- a/pypy/module/signal/__init__.py
+++ b/pypy/module/signal/__init__.py
@@ -26,6 +26,7 @@
             interpleveldefs[name] = 'space.wrap(interp_signal.%s)' % (name,)
 
     if os.name == 'posix':
+        interpleveldefs['sigwait'] = 'interp_signal.sigwait'
         interpleveldefs['pthread_kill'] = 'interp_signal.pthread_kill'
 
     appleveldefs = {
diff --git a/pypy/module/signal/interp_signal.py b/pypy/module/signal/interp_signal.py
--- a/pypy/module/signal/interp_signal.py
+++ b/pypy/module/signal/interp_signal.py
@@ -5,14 +5,14 @@
 import os
 import errno
 
-from pypy.interpreter.error import OperationError, exception_from_errno
+from pypy.interpreter.error import OperationError, oefmt, exception_from_errno
 from pypy.interpreter.executioncontext import (AsyncAction, AbstractActionFlag,
     PeriodicAsyncAction)
 from pypy.interpreter.gateway import unwrap_spec
 
 from rpython.rlib import jit, rposix, rgc
 from rpython.rlib.objectmodel import we_are_translated
-from rpython.rlib.rarithmetic import intmask
+from rpython.rlib.rarithmetic import intmask, widen
 from rpython.rlib.rsignal import *
 from rpython.rtyper.lltypesystem import lltype, rffi
 
@@ -334,7 +334,38 @@
 def pthread_kill(space, tid, signum):
     "Send a signal to a thread."
     ret = c_pthread_kill(tid, signum)
-    if ret != 0:
+    if widen(ret) < 0:
         raise exception_from_errno(space, space.w_OSError)
     # the signal may have been send to the current thread
     space.getexecutioncontext().checksignals()
+
+
+class SignalMask(object):
+    def __init__(self, space, w_signals):
+        self.space = space
+        self.w_signals = w_signals
+
+    def __enter__(self):
+        space = self.space
+        self.mask = lltype.malloc(c_sigset_t.TO, flavor='raw')
+        c_sigemptyset(self.mask)
+        for w_signum in space.unpackiterable(self.w_signals):
+            signum = space.int_w(w_signum)
+            check_signum_in_range(space, signum)
+            err = c_sigaddset(self.mask, signum)
+            if err:
+                raise oefmt(space.w_ValueError,
+                            "signal number %d out of range", signum)
+        return self.mask
+
+    def __exit__(self, *args):
+        lltype.free(self.mask, flavor='raw')
+
+def sigwait(space, w_signals):
+    with SignalMask(space, w_signals) as sigset:
+        with lltype.scoped_alloc(rffi.INTP.TO, 1) as signum_ptr:
+            ret = c_sigwait(sigset, signum_ptr)
+            if ret != 0:
+                raise exception_from_errno(space, space.w_OSError)
+            signum = signum_ptr[0]
+    return space.wrap(signum)
diff --git a/pypy/module/signal/test/test_signal.py b/pypy/module/signal/test/test_signal.py
--- a/pypy/module/signal/test/test_signal.py
+++ b/pypy/module/signal/test/test_signal.py
@@ -333,3 +333,12 @@
         tid = _thread.get_ident()
         raises(ZeroDivisionError, signal.pthread_kill, tid, signum)
         
+    def test_sigwait(self):
+        import signal
+        def handler(signum, frame):
+            1/0
+        signal.signal(signal.SIGALRM, handler)
+        signal.alarm(1)
+        received = signal.sigwait([signal.SIGALRM])
+        assert received == signal.SIGALRM
+        
diff --git a/rpython/rlib/rsignal.py b/rpython/rlib/rsignal.py
--- a/rpython/rlib/rsignal.py
+++ b/rpython/rlib/rsignal.py
@@ -98,3 +98,9 @@
     c_getitimer = external('getitimer', [rffi.INT, itimervalP], rffi.INT)
 
 c_pthread_kill = external('pthread_kill', [lltype.Signed, rffi.INT], rffi.INT)
+
+if sys.platform != 'win32':
+    c_sigset_t = rffi.COpaquePtr('sigset_t', compilation_info=eci)
+    c_sigemptyset = external('sigemptyset', [c_sigset_t], rffi.INT)
+    c_sigaddset = external('sigaddset', [c_sigset_t, rffi.INT], rffi.INT)
+    c_sigwait = external('sigwait', [c_sigset_t, rffi.INTP], rffi.INT)


More information about the pypy-commit mailing list