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

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


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: py3.3
Changeset: r75231:849428da8b0f
Date: 2015-01-04 18:51 +0100
http://bitbucket.org/pypy/pypy/changeset/849428da8b0f/

Log:	Add signal.pthread_sigmask()

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
@@ -28,6 +28,10 @@
     if os.name == 'posix':
         interpleveldefs['sigwait'] = 'interp_signal.sigwait'
         interpleveldefs['pthread_kill'] = 'interp_signal.pthread_kill'
+        interpleveldefs['pthread_sigmask'] = 'interp_signal.pthread_sigmask'
+        interpleveldefs['SIG_BLOCK'] = 'space.wrap(interp_signal.SIG_BLOCK)'
+        interpleveldefs['SIG_UNBLOCK'] = 'space.wrap(interp_signal.SIG_UNBLOCK)'
+        interpleveldefs['SIG_SETMASK'] = 'space.wrap(interp_signal.SIG_SETMASK)'
 
     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
@@ -361,6 +361,19 @@
     def __exit__(self, *args):
         lltype.free(self.mask, flavor='raw')
 
+def _sigset_to_signals(space, mask):
+    signals_w = []
+    for sig in range(1, NSIG):
+        if c_sigismember(mask, sig) != 1:
+            continue
+        # Handle the case where it is a member by adding the signal to
+        # the result list.  Ignore the other cases because they mean
+        # the signal isn't a member of the mask or the signal was
+        # invalid, and an invalid signal must have been our fault in
+        # constructing the loop boundaries.
+        signals_w.append(space.wrap(sig))
+    return space.call_function(space.w_set, space.newtuple(signals_w))
+
 def sigwait(space, w_signals):
     with SignalMask(space, w_signals) as sigset:
         with lltype.scoped_alloc(rffi.INTP.TO, 1) as signum_ptr:
@@ -369,3 +382,14 @@
                 raise exception_from_errno(space, space.w_OSError)
             signum = signum_ptr[0]
     return space.wrap(signum)
+
+ at unwrap_spec(how=int)
+def pthread_sigmask(space, how, w_signals):
+    with SignalMask(space, w_signals) as sigset:
+        with lltype.scoped_alloc(c_sigset_t.TO) as previous:
+            ret = c_pthread_sigmask(how, sigset, previous)
+            if ret != 0:
+                raise exception_from_errno(space, space.w_OSError)
+            # if signals was unblocked, signal handlers have been called
+            space.getexecutioncontext().checksignals()
+            return _sigset_to_signals(space, previous)
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
@@ -342,3 +342,18 @@
         received = signal.sigwait([signal.SIGALRM])
         assert received == signal.SIGALRM
         
+    def test_sigmask(self):
+        import signal, posix
+        signum1 = signal.SIGUSR1
+        signum2 = signal.SIGUSR2
+
+        def handler(signum, frame):
+            pass
+        signal.signal(signum1, handler)
+        signal.signal(signum2, handler)
+
+        signal.pthread_sigmask(signal.SIG_BLOCK, (signum1, signum2))
+        posix.kill(posix.getpid(), signum1)
+        posix.kill(posix.getpid(), signum2)
+        # Unblocking the 2 signals calls the C signal handler twice
+        signal.pthread_sigmask(signal.SIG_UNBLOCK, (signum1, signum2))
diff --git a/rpython/rlib/rsignal.py b/rpython/rlib/rsignal.py
--- a/rpython/rlib/rsignal.py
+++ b/rpython/rlib/rsignal.py
@@ -31,7 +31,7 @@
     signal_names.append('CTRL_BREAK_EVENT')
     CTRL_C_EVENT = 0
     CTRL_BREAK_EVENT = 1
-includes = ['stdlib.h', 'src/signals.h']
+includes = ['stdlib.h', 'src/signals.h', 'signal.h']
 if sys.platform != 'win32':
     includes.append('sys/time.h')
 
@@ -47,7 +47,9 @@
     _compilation_info_ = eci
 
 if sys.platform != 'win32':
-    for name in """ITIMER_REAL ITIMER_VIRTUAL ITIMER_PROF""".split():
+    for name in """
+        ITIMER_REAL ITIMER_VIRTUAL ITIMER_PROF
+        SIG_BLOCK SIG_UNBLOCK SIG_SETMASK""".split():
         setattr(CConfig, name, rffi_platform.DefinedConstantInteger(name))
 
     CConfig.timeval = rffi_platform.Struct(
@@ -103,4 +105,7 @@
     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_sigismember = external('sigismember', [c_sigset_t, rffi.INT], rffi.INT)
     c_sigwait = external('sigwait', [c_sigset_t, rffi.INTP], rffi.INT)
+    c_pthread_sigmask = external('pthread_sigmask',
+                                 [rffi.INT, c_sigset_t, c_sigset_t], rffi.INT)


More information about the pypy-commit mailing list