[pypy-svn] pypy default: Add signal.setitimer, signal.getitimer

amauryfa commits-noreply at bitbucket.org
Wed Jan 19 00:30:09 CET 2011


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: 
Changeset: r40912:c9973ba1a131
Date: 2011-01-19 00:24 +0100
http://bitbucket.org/pypy/pypy/changeset/c9973ba1a131/

Log:	Add signal.setitimer, signal.getitimer

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
@@ -1,6 +1,7 @@
 
 from pypy.interpreter.mixedmodule import MixedModule
 import os
+import signal as cpy_signal
 
 class Module(MixedModule):
     interpleveldefs = {
@@ -17,6 +18,12 @@
         interpleveldefs['pause'] = 'interp_signal.pause'
         interpleveldefs['siginterrupt'] = 'interp_signal.siginterrupt'
 
+    if hasattr(cpy_signal, 'setitimer'):
+        interpleveldefs['setitimer'] = 'interp_signal.setitimer'
+        interpleveldefs['getitimer'] = 'interp_signal.getitimer'
+        for name in ['ITIMER_REAL', 'ITIMER_VIRTUAL', 'ITIMER_PROF']:
+            interpleveldefs[name] = 'space.wrap(interp_signal.%s)' % (name,)
+
     appleveldefs = {
         'default_int_handler': 'app_signal.default_int_handler',
     }

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
@@ -236,3 +236,22 @@
             alarm(0)
         finally:
             signal(SIGALRM, SIG_DFL)
+
+class AppTestItimer:
+    def test_itimer_real(self):
+        import signal
+
+        def sig_alrm(*args):
+            self.called = True
+
+        signal.signal(signal.SIGALRM, sig_alrm)
+        old = signal.setitimer(signal.ITIMER_REAL, 1.0)
+        assert old == (0, 0)
+
+        val, interval = signal.getitimer(signal.ITIMER_REAL)
+        assert val <= 1.0
+        assert interval == 0.0
+
+        signal.pause()
+        assert self.called
+

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
@@ -2,10 +2,13 @@
 from pypy.interpreter.baseobjspace import W_Root, ObjSpace
 from pypy.interpreter.executioncontext import AsyncAction, AbstractActionFlag
 from pypy.interpreter.executioncontext import PeriodicAsyncAction
+from pypy.interpreter.gateway import unwrap_spec
 import signal as cpy_signal
 from pypy.rpython.lltypesystem import lltype, rffi
+from pypy.rpython.tool import rffi_platform
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 import py
+import sys
 from pypy.tool import autopath
 from pypy.rlib import jit, rposix
 from pypy.rlib.rarithmetic import intmask
@@ -21,8 +24,12 @@
 SIG_IGN = cpy_signal.SIG_IGN
 signal_names = list(setup())
 
+includes = ['stdlib.h', 'src/signals.h']
+if sys.platform != 'win32':
+    includes.append('sys/time.h')
+
 eci = ExternalCompilationInfo(
-    includes = ['stdlib.h', 'src/signals.h'],
+    includes = includes,
     separate_module_sources = ['#include <src/signals.h>'],
     include_dirs = [str(py.path.local(autopath.pypydir).join('translator', 'c'))],
     export_symbols = ['pypysig_poll', 'pypysig_default',
@@ -31,6 +38,28 @@
                       'pypysig_getaddr_occurred'],
 )
 
+class CConfig:
+    _compilation_info_ = eci
+
+    for name in """ITIMER_REAL ITIMER_VIRTUAL ITIMER_PROF""".split():
+        locals()[name] = rffi_platform.DefinedConstantInteger(name)
+
+
+    timeval = rffi_platform.Struct(
+        'struct timeval',
+        [('tv_sec', rffi.LONG),
+         ('tv_usec', rffi.LONG)])
+
+    itimerval = rffi_platform.Struct(
+        'struct itimerval',
+        [('it_value', timeval),
+         ('it_interval', timeval)])
+
+for k, v in rffi_platform.configure(CConfig).items():
+    globals()[k] = v
+
+itimervalP = rffi.CArrayPtr(itimerval)
+
 def external(name, args, result, **kwds):
     return rffi.llexternal(name, args, result, compilation_info=eci, **kwds)
 
@@ -55,6 +84,10 @@
 c_pause = external('pause', [], rffi.INT)
 c_siginterrupt = external('siginterrupt', [rffi.INT, rffi.INT], rffi.INT)
 
+c_setitimer = external('setitimer',
+                       [rffi.INT, itimervalP, itimervalP], rffi.INT)
+c_getitimer = external('getitimer', [rffi.INT, itimervalP], rffi.INT)
+
 
 class SignalActionFlag(AbstractActionFlag):
     # This class uses the C-level pypysig_counter variable as the tick
@@ -252,3 +285,39 @@
         errno = rposix.get_errno()
         raise OperationError(space.w_RuntimeError, space.wrap(errno))
 siginterrupt.unwrap_spec = [ObjSpace, int, int]
+
+
+#__________________________________________________________
+
+def timeval_from_double(d, timeval):
+    timeval.c_tv_sec = int(d)
+    timeval.c_tv_usec = int((d - int(d)) * 1000000)
+
+def double_from_timeval(tv):
+    return tv.c_tv_sec + (tv.c_tv_usec / 1000000.0)
+
+def itimer_retval(space, val):
+    w_value = space.wrap(double_from_timeval(val.c_it_value))
+    w_interval = space.wrap(double_from_timeval(val.c_it_interval))
+    return space.newtuple([w_value, w_interval])
+
+ at unwrap_spec(ObjSpace, int, float, float)
+def setitimer(space, which, first, interval=0):
+    with lltype.scoped_alloc(itimervalP.TO, 1) as new:
+
+        timeval_from_double(first, new[0].c_it_value)
+        timeval_from_double(interval, new[0].c_it_interval)
+
+        with lltype.scoped_alloc(itimervalP.TO, 1) as old:
+
+            c_setitimer(which, new, old)
+
+            return itimer_retval(space, old[0])
+
+ at unwrap_spec(ObjSpace, int)
+def getitimer(space, which):
+    with lltype.scoped_alloc(itimervalP.TO, 1) as old:
+
+        c_getitimer(which, old)
+
+        return itimer_retval(space, old[0])


More information about the Pypy-commit mailing list