Author: Armin Rigo <[email protected]>
Branch: stm-thread-2
Changeset: r60599:ab8f8aab5c76
Date: 2013-01-28 10:51 +0100
http://bitbucket.org/pypy/pypy/changeset/ab8f8aab5c76/
Log: Copy the same simplification as in trunk.
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
@@ -40,11 +40,11 @@
def __init__(self, space, *args):
"NOT_RPYTHON"
- from pypy.module.signal import sigaction
+ from pypy.module.signal import interp_signal
MixedModule.__init__(self, space, *args)
# add the signal-checking callback as an action on the space
- space.check_signal_action = sigaction.CheckSignalAction(space)
+ space.check_signal_action = interp_signal.CheckSignalAction(space)
space.actionflag.register_periodic_action(space.check_signal_action,
use_bytecode_counter=False)
- space.actionflag.__class__ = sigaction.SignalActionFlag
+ space.actionflag.__class__ = interp_signal.SignalActionFlag
# xxx yes I know the previous line is a hack
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
@@ -1,10 +1,101 @@
from __future__ import with_statement
+
+import signal as cpy_signal
+
from pypy.interpreter.error import OperationError, exception_from_errno
+from pypy.interpreter.executioncontext import (AsyncAction, AbstractActionFlag,
+ PeriodicAsyncAction)
from pypy.interpreter.gateway import unwrap_spec
-from pypy.rpython.lltypesystem import lltype, rffi
+
from pypy.rlib import jit, rposix
from pypy.rlib.rarithmetic import intmask
-from pypy.rlib.rsignal import *
+from pypy.rlib.rsignal import (pypysig_getaddr_occurred, pypysig_setflag,
+ pypysig_poll, pypysig_reinstall, pypysig_ignore, pypysig_default,
+ pypysig_set_wakeup_fd, c_alarm, c_pause, c_getitimer, c_setitimer,
+ c_siginterrupt, itimervalP, NSIG, SIG_DFL, SIG_IGN, ITIMER_REAL,
+ ITIMER_PROF, ITIMER_VIRTUAL, signal_values)
+from pypy.rpython.lltypesystem import lltype, rffi
+
+
+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. This causes CheckSignalAction.perform() to
+ # be called.
+
+ def get_ticker(self):
+ p = pypysig_getaddr_occurred()
+ return p.c_value
+
+ def reset_ticker(self, value):
+ p = pypysig_getaddr_occurred()
+ p.c_value = value
+
+ def decrement_ticker(self, by):
+ p = pypysig_getaddr_occurred()
+ value = p.c_value
+ if self.has_bytecode_counter: # this 'if' is constant-folded
+ if jit.isconstant(by) and by == 0:
+ pass # normally constant-folded too
+ else:
+ value -= by
+ p.c_value = value
+ return value
+
+
+class CheckSignalAction(PeriodicAsyncAction):
+ """An action that is automatically invoked when a signal is received."""
+
+ def __init__(self, space):
+ AsyncAction.__init__(self, space)
+ self.handlers_w = {}
+ self.emulated_sigint = False
+
+ @jit.dont_look_inside
+ def perform(self, executioncontext, frame):
+ if self.space.config.objspace.usemodules.thread:
+ main_ec = self.space.threadlocals.getmainthreadvalue()
+ in_main = executioncontext is main_ec
+ else:
+ 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.emulated_sigint = True
+ self.perform(ec, None)
+
+ def _report_signal(self, n):
+ try:
+ w_handler = self.handlers_w[n]
+ except KeyError:
+ return # no handler, ignore signal
+ space = self.space
+ if not space.is_true(space.callable(w_handler)):
+ return # w_handler is SIG_IGN or SIG_DFL?
+ # re-install signal handler, for OSes that clear it
+ pypysig_reinstall(n)
+ # invoke the app-level handler
+ ec = space.getexecutioncontext()
+ w_frame = space.wrap(ec.gettopframe_nohidden())
+ space.call_function(w_handler, space.wrap(n), w_frame)
@unwrap_spec(signum=int)
diff --git a/pypy/module/signal/sigaction.py b/pypy/module/signal/sigaction.py
deleted file mode 100644
--- a/pypy/module/signal/sigaction.py
+++ /dev/null
@@ -1,123 +0,0 @@
-from pypy.interpreter.executioncontext import AsyncAction, AbstractActionFlag
-from pypy.interpreter.executioncontext import PeriodicAsyncAction
-from pypy.rlib import jit
-from pypy.rlib.rsignal import pypysig_getaddr_occurred
-from pypy.rlib.rsignal import pypysig_poll, pypysig_reinstall
-
-
-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.
-
- def get_ticker(self):
- p = pypysig_getaddr_occurred()
- return p.c_value
-
- def reset_ticker(self, value):
- p = pypysig_getaddr_occurred()
- p.c_value = value
-
- def decrement_ticker(self, by):
- p = pypysig_getaddr_occurred()
- value = p.c_value
- if self.has_bytecode_counter: # this 'if' is constant-folded
- if jit.isconstant(by) and by == 0:
- pass # normally constant-folded too
- else:
- value -= by
- p.c_value = value
- return value
-
-
-class CheckSignalAction(PeriodicAsyncAction):
- """An action that is automatically invoked when a signal is received."""
-
- 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
-
- @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)
- 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()
-
- @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)
-
- @jit.dont_look_inside
- def report_signal(self, n):
- try:
- w_handler = self.handlers_w[n]
- except KeyError:
- return # no handler, ignore signal
- space = self.space
- if not space.is_true(space.callable(w_handler)):
- return # w_handler is SIG_IGN or SIG_DFL?
- # re-install signal handler, for OSes that clear it
- pypysig_reinstall(n)
- # invoke the app-level handler
- ec = space.getexecutioncontext()
- 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()
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit