[pypy-svn] r34072 - in pypy/dist/pypy: interpreter module/signal module/signal/test module/thread translator/goal
arigo at codespeak.net
arigo at codespeak.net
Thu Nov 2 19:06:49 CET 2006
Author: arigo
Date: Thu Nov 2 19:06:46 2006
New Revision: 34072
Added:
pypy/dist/pypy/module/signal/ (props changed)
pypy/dist/pypy/module/signal/__init__.py (contents, props changed)
pypy/dist/pypy/module/signal/ctypes_signal.py (contents, props changed)
pypy/dist/pypy/module/signal/interp_signal.py (contents, props changed)
pypy/dist/pypy/module/signal/test/ (props changed)
pypy/dist/pypy/module/signal/test/test_signal.py (contents, props changed)
Modified:
pypy/dist/pypy/interpreter/executioncontext.py
pypy/dist/pypy/interpreter/miscutils.py
pypy/dist/pypy/module/thread/threadlocals.py
pypy/dist/pypy/translator/goal/app_main.py
Log:
Rough sketch of the 'signal' module. Work in progress.
When pypy-c finds it, i.e. when translated --withmod-signal,
it should install a handler for Ctrl-C.
Modified: pypy/dist/pypy/interpreter/executioncontext.py
==============================================================================
--- pypy/dist/pypy/interpreter/executioncontext.py (original)
+++ pypy/dist/pypy/interpreter/executioncontext.py Thu Nov 2 19:06:46 2006
@@ -107,8 +107,8 @@
# as selected by sys.setcheckinterval()
ticker = self.ticker
if ticker <= 0:
- Action.perform_actions(self.pending_actions)
Action.perform_actions(self.space.pending_actions)
+ Action.perform_actions(self.pending_actions)
ticker = self.space.sys.checkinterval
self.ticker = ticker - 1
if frame.w_f_trace is None or self.is_tracing:
Modified: pypy/dist/pypy/interpreter/miscutils.py
==============================================================================
--- pypy/dist/pypy/interpreter/miscutils.py (original)
+++ pypy/dist/pypy/interpreter/miscutils.py Thu Nov 2 19:06:46 2006
@@ -165,6 +165,9 @@
def setvalue(self, value):
self._value = value
+ def getmainthreadvalue(self):
+ return self._value
+
def getGIL(self):
return None # XXX temporary hack!
Added: pypy/dist/pypy/module/signal/__init__.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/signal/__init__.py Thu Nov 2 19:06:46 2006
@@ -0,0 +1,26 @@
+
+from pypy.interpreter.mixedmodule import MixedModule
+
+class Module(MixedModule):
+ interpleveldefs = {
+ 'signal': 'interp_signal.signal',
+ }
+
+ appleveldefs = {
+ }
+
+ def buildloaders(cls):
+ from pypy.module.signal import ctypes_signal
+ for name in ctypes_signal.signal_names:
+ signum = getattr(ctypes_signal, name)
+ if signum is not None:
+ Module.interpleveldefs[name] = 'space.wrap(%d)' % (signum,)
+ super(Module, cls).buildloaders()
+ buildloaders = classmethod(buildloaders)
+
+ def __init__(self, space, *args):
+ "NOT_RPYTHON"
+ from pypy.module.signal.interp_signal import CheckSignalAction
+ MixedModule.__init__(self, space, *args)
+ # add the signal-checking callback as an action on the space
+ space.pending_actions.append(CheckSignalAction(space))
Added: pypy/dist/pypy/module/signal/ctypes_signal.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/signal/ctypes_signal.py Thu Nov 2 19:06:46 2006
@@ -0,0 +1,33 @@
+from pypy.rpython.rctypes.tool import ctypes_platform
+from pypy.rpython.rctypes.tool.libc import libc
+from ctypes import *
+
+
+signal_names = ['SIGINT', 'SIGTERM', 'SIGKILL',
+ # ...
+ ]
+
+
+sighandler_t = CFUNCTYPE(None, c_int)
+
+signal = libc.signal
+signal.restype = sighandler_t
+signal.argtypes = [c_int, sighandler_t]
+
+
+class CConfig:
+ _includes_ = ('signal.h',)
+
+## struct_sigaction = ctypes_platform.Struct('struct sigaction',
+## [('sa_handler', sighandler_t)])
+
+for name in signal_names:
+ setattr(CConfig, name, ctypes_platform.DefinedConstantInteger(name))
+
+globals().update(ctypes_platform.configure(CConfig))
+
+
+##sigaction = libc.sigaction
+##sigaction.restype = c_int
+##sigaction.argtypes = [c_int, POINTER(struct_sigaction),
+## POINTER(struct_sigaction)]
Added: pypy/dist/pypy/module/signal/interp_signal.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/signal/interp_signal.py Thu Nov 2 19:06:46 2006
@@ -0,0 +1,105 @@
+from pypy.interpreter.baseobjspace import W_Root, ObjSpace
+from pypy.interpreter.miscutils import Action
+from pypy.module.signal import ctypes_signal
+
+
+class CheckSignalAction(Action):
+ """A repeatitive action at the space level, checking if the
+ signal_occurred flag is set and if so, scheduling ReportSignal actions.
+ """
+ repeat = True
+
+ def __init__(self, space):
+ self.space = space
+
+ def perform(self):
+ if flag_queue.signal_occurred:
+ flag_queue.signal_occurred = 0
+ node = flag_queue.head
+ signum = 0
+ while node is not None:
+ if node.flag:
+ node.flag = 0
+ main_ec = self.space.threadlocals.getmainthreadvalue()
+ main_ec.add_pending_action(ReportSignal(self.space,
+ node, signum))
+ node = node.next
+ signum += 1
+
+
+class ReportSignal(Action):
+ """A one-shot action for the main thread's execution context."""
+
+ def __init__(self, space, node, signum):
+ self.space = space
+ self.node = node
+ self.signum = signum
+
+ def perform(self):
+ w_handler = self.node.w_handler
+ if w_handler is not None:
+ space = self.space
+ ec = space.getexecutioncontext()
+ try:
+ w_frame = ec.framestack.top()
+ except IndexError:
+ w_frame = space.w_None
+ space.call_function(w_handler, space.wrap(self.signum), w_frame)
+
+
+# ____________________________________________________________
+# Global flags set by the signal handler
+
+# XXX some of these data structures may need to
+# use the "volatile" keyword in the generated C code
+
+class FlagQueueNode(object):
+ def __init__(self):
+ self.flag = 0
+ self.next = None
+ self.w_handler = None
+
+class FlagQueue(object):
+ signal_occurred = 0
+ head = FlagQueueNode()
+
+flag_queue = FlagQueue()
+
+def get_flag_queue_signum(signum):
+ node = flag_queue.head
+ while signum > 0:
+ if node.next is None:
+ node.next = FlagQueueNode()
+ node = node.next
+ signum -= 1
+ return node
+
+def generic_signal_handler(signum):
+ node = flag_queue.head
+ index = 0
+ while index < signum:
+ node = node.next
+ index += 1
+ node.flag = 1
+ flag_queue.signal_occurred = 1
+ # XXX may need to set the handler again, in case the OS clears it
+
+def os_setsig(signum, handler):
+ return ctypes_signal.signal(signum, handler)
+
+# ____________________________________________________________
+
+def signal(space, signum, w_handler):
+ ec = space.getexecutioncontext()
+ main_ec = space.threadlocals.getmainthreadvalue()
+ if ec is not main_ec:
+ raise OperationError(space.w_ValueError,
+ space.wrap("signal() must be called from the "
+ "main thread"))
+ node = get_flag_queue_signum(signum)
+ node.w_handler = w_handler
+ # XXX special values SIG_IGN, SIG_DFL
+ handler = ctypes_signal.sighandler_t(generic_signal_handler)
+ os_setsig(signum, handler)
+ # XXX return value
+signal.unwrap_spec = [ObjSpace, int, W_Root]
Added: pypy/dist/pypy/module/signal/test/test_signal.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/signal/test/test_signal.py Thu Nov 2 19:06:46 2006
@@ -0,0 +1,13 @@
+
+##import signal
+
+##def ya(*args):
+## print "ya", args
+
+##signal.signal(signal.SIGINT, ya)
+
+##i = 0
+##while 1:
+## i += 1
+## if i%1000 == 0:
+## print i
Modified: pypy/dist/pypy/module/thread/threadlocals.py
==============================================================================
--- pypy/dist/pypy/module/thread/threadlocals.py (original)
+++ pypy/dist/pypy/module/thread/threadlocals.py Thu Nov 2 19:06:46 2006
@@ -12,6 +12,7 @@
def __init__(self):
self._valuedict = {} # {thread_ident: ExecutionContext()}
+ self._mainthreadident = 0
def getvalue(self):
ident = thread.get_ident()
@@ -19,7 +20,19 @@
def setvalue(self, value):
ident = thread.get_ident()
- self._valuedict[ident] = value
+ if value is not None:
+ if len(self._valuedict) == 0:
+ self._mainthreadident = ident
+ self._valuedict[ident] = value
+ else:
+ try:
+ del self._valuedict[ident]
+ except KeyError:
+ pass
+
+ def getmainthreadvalue(self):
+ ident = self._mainthreadident
+ return self._valuedict.get(ident, None)
def enter_thread(self, space):
"Notification that the current thread is just starting."
Modified: pypy/dist/pypy/translator/goal/app_main.py
==============================================================================
--- pypy/dist/pypy/translator/goal/app_main.py (original)
+++ pypy/dist/pypy/translator/goal/app_main.py Thu Nov 2 19:06:46 2006
@@ -198,6 +198,17 @@
mainmodule = type(sys)('__main__')
sys.modules['__main__'] = mainmodule
+ # set up the Ctrl-C => KeyboardInterrupt signal handler, if the
+ # signal module is available
+ try:
+ import signal
+ except ImportError:
+ pass
+ else:
+ def keyboard_interrupt_handler(*args):
+ raise KeyboardInterrupt
+ signal.signal(signal.SIGINT, keyboard_interrupt_handler)
+
try:
if sys.argv:
if sys.argv[0] == '-c':
More information about the Pypy-commit
mailing list