[pypy-commit] pypy default: merge heads

bdkearns noreply at buildbot.pypy.org
Mon Jan 28 09:54:15 CET 2013


Author: Brian Kearns <bdkearns at gmail.com>
Branch: 
Changeset: r60588:d1767635d7c4
Date: 2013-01-28 03:54 -0500
http://bitbucket.org/pypy/pypy/changeset/d1767635d7c4/

Log:	merge heads

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
@@ -19,7 +19,8 @@
 class SignalActionFlag(AbstractActionFlag):
     # This class uses the C-level pypysig_counter variable as the tick
     # counter.  The C-level signal handler will reset it to -1 whenever
-    # a signal is received.
+    # a signal is received.  This causes CheckSignalAction.perform() to
+    # be called.
 
     def get_ticker(self):
         p = pypysig_getaddr_occurred()
@@ -47,45 +48,40 @@
     def __init__(self, space):
         AsyncAction.__init__(self, space)
         self.handlers_w = {}
-        if space.config.objspace.usemodules.thread:
-            # need a helper action in case signals arrive in a non-main thread
-            self.pending_signals = {}
-            self.reissue_signal_action = ReissueSignalAction(space)
-        else:
-            self.reissue_signal_action = None
+        self.emulated_sigint = False
 
     @jit.dont_look_inside
     def perform(self, executioncontext, frame):
-        while True:
-            n = pypysig_poll()
-            if n < 0:
-                break
-            self.perform_signal(executioncontext, n)
-
-    @jit.dont_look_inside
-    def perform_signal(self, executioncontext, n):
-        if self.reissue_signal_action is None:
-            # no threads: we can report the signal immediately
-            self.report_signal(n)
+        if self.space.config.objspace.usemodules.thread:
+            main_ec = self.space.threadlocals.getmainthreadvalue()
+            in_main = executioncontext is main_ec
         else:
-            main_ec = self.space.threadlocals.getmainthreadvalue()
-            if executioncontext is main_ec:
-                # running in the main thread: we can report the
-                # signal immediately
-                self.report_signal(n)
-            else:
-                # running in another thread: we need to hack a bit
-                self.pending_signals[n] = None
-                self.reissue_signal_action.fire_after_thread_switch()
+            in_main = True
+        # If we are in the main thread, poll and report the signals now.
+        if in_main:
+            if self.emulated_sigint:
+                self.emulated_sigint = False
+                self._report_signal(cpy_signal.SIGINT)
+            while True:
+                n = pypysig_poll()
+                if n < 0:
+                    break
+                self._report_signal(n)
+        else:
+            # Otherwise, don't call pypysig_poll() at all.  Instead,
+            # arrange for perform() to be called again after a thread
+            # switch.  It might be called again and again, until we
+            # land in the main thread.
+            self.fire_after_thread_switch()
 
     @jit.dont_look_inside
     def set_interrupt(self):
         "Simulates the effect of a SIGINT signal arriving"
         ec = self.space.getexecutioncontext()
-        self.perform_signal(ec, cpy_signal.SIGINT)
+        self.emulated_sigint = True
+        self.perform(ec, None)
 
-    @jit.dont_look_inside
-    def report_signal(self, n):
+    def _report_signal(self, n):
         try:
             w_handler = self.handlers_w[n]
         except KeyError:
@@ -100,39 +96,6 @@
         w_frame = space.wrap(ec.gettopframe_nohidden())
         space.call_function(w_handler, space.wrap(n), w_frame)
 
-    @jit.dont_look_inside
-    def report_pending_signals(self):
-        # XXX this logic isn't so complicated but I have no clue how
-        # to test it :-(
-        pending_signals = self.pending_signals.keys()
-        self.pending_signals.clear()
-        try:
-            while pending_signals:
-                self.report_signal(pending_signals.pop())
-        finally:
-            # in case of exception, put the undelivered signals back
-            # into the dict instead of silently swallowing them
-            if pending_signals:
-                for n in pending_signals:
-                    self.pending_signals[n] = None
-                self.reissue_signal_action.fire()
-
-
-class ReissueSignalAction(AsyncAction):
-    """A special action to help deliver signals to the main thread.  If
-    a non-main thread caught a signal, this action fires after every
-    thread switch until we land in the main thread.
-    """
-
-    def perform(self, executioncontext, frame):
-        main_ec = self.space.threadlocals.getmainthreadvalue()
-        if executioncontext is main_ec:
-            # now running in the main thread: we can really report the signals
-            self.space.check_signal_action.report_pending_signals()
-        else:
-            # still running in some other thread: try again later
-            self.fire_after_thread_switch()
-
 
 @unwrap_spec(signum=int)
 def getsignal(space, signum):
diff --git a/pypy/module/thread/os_local.py b/pypy/module/thread/os_local.py
--- a/pypy/module/thread/os_local.py
+++ b/pypy/module/thread/os_local.py
@@ -98,5 +98,5 @@
         local = wref()
         if local is not None:
             del local.dicts[ec]
-        local.last_dict = None
-        local.last_ec = None
+            local.last_dict = None
+            local.last_ec = None


More information about the pypy-commit mailing list