def test_alarm_raise(self): try: from _signal import alarm, signal, SIG_DFL, SIGALRM except ImportError: skip("no SIGALRM on this platform") import _socket class Alarm(Exception): pass def handler(*a): raise Alarm() s = _socket.socket() s.listen(1) try: signal(SIGALRM, handler) alarm(1) try: s._accept() except Alarm: pass else: raise Exception("should have raised Alarm") alarm(0) finally: signal(SIGALRM, SIG_DFL)
def step(self): """Invokes the task manager for one frame, and then returns. Normally, this executes each task exactly once, though task chains that are in sub-threads or that have frame budgets might execute their tasks differently. """ startFrameTime = self.globalClock.getRealTime() # Replace keyboard interrupt handler during task list processing # so we catch the keyboard interrupt but don't handle it until # after task list processing is complete. self.fKeyboardInterrupt = 0 self.interruptCount = 0 if signal: self.__prevHandler = signal.signal(signal.SIGINT, self.keyboardInterruptHandler) try: self.mgr.poll() # This is the spot for an internal yield function nextTaskTime = self.mgr.getNextWakeTime() self.doYield(startFrameTime, nextTaskTime) finally: # Restore previous interrupt handler if signal: signal.signal(signal.SIGINT, self.__prevHandler) self.__prevHandler = signal.default_int_handler if self.fKeyboardInterrupt: raise KeyboardInterrupt
def invokeDefaultHandler(self, signalNumber, stackFrame): print('*** allowing mid-frame keyboard interrupt.') # Restore default interrupt handler if signal: signal.signal(signal.SIGINT, self.__prevHandler) # and invoke it raise KeyboardInterrupt
def keyboardInterruptHandler(self, signalNumber, stackFrame): self.fKeyboardInterrupt = 1 self.interruptCount += 1 if self.interruptCount == 1: print('* interrupt by keyboard') elif self.interruptCount == 2: print('** waiting for end of frame before interrupting...') # The user must really want to interrupt this process # Next time around invoke the default handler signal.signal(signal.SIGINT, self.invokeDefaultHandler)
def test_default_return(self): """ Test that signal.signal returns SIG_DFL if that is the current handler. """ from _signal import signal, SIGINT, SIG_DFL, SIG_IGN try: for handler in SIG_DFL, SIG_IGN, lambda *a: None: signal(SIGINT, SIG_DFL) assert signal(SIGINT, handler) == SIG_DFL finally: signal(SIGINT, SIG_DFL)
def test_args_validation(self): try: import _signal except ImportError: import signal as _signal self.assertRaises(OverflowError, lambda: _signal.signal(0x8000000000000000, 0)) self.assertRaises(OverflowError, lambda: _signal.signal(0x800000000000000, 0)) self.assertRaises(TypeError, lambda: _signal.signal(_signal.SIGALRM, 0x100)) self.assertRaises(TypeError, lambda: _signal.signal(_signal.SIGALRM, 'string'))
def test_alarm2(): try: import _signal except ImportError: import signal as _signal import time triggered = None def handler(signal, frame): nonlocal triggered caller_code = sys._getframe(1).f_code assert caller_code == test_alarm2.__code__, "expected: '%s' but was '%s'" % ( test_alarm2.__code__, caller_code) triggered = (signal, frame) oldhandler = _signal.signal(_signal.SIGALRM, handler) assert oldhandler == _signal.SIG_DFL, "oldhandler != SIG_DFL" assert _signal.getsignal( _signal.SIGALRM) is handler, "getsignal handler != handler" _signal.alarm(1) while not triggered: time.sleep(0.5) assert triggered[0] == _signal.SIGALRM assert triggered[1].f_code.co_name == "test_alarm2", triggered[1].f_code
def test_alarm2(): try: import _signal except ImportError: import signal as _signal import time triggered = None def handler(signal, frame): nonlocal triggered triggered = (signal, frame) oldhandler = _signal.signal(_signal.SIGALRM, handler) assert oldhandler == _signal.SIG_DFL, "oldhandler != SIG_DFL" assert _signal.getsignal( _signal.SIGALRM) is handler, "getsignal handler != handler" _signal.alarm(1) while not triggered: time.sleep(0.5) assert triggered[0] == _signal.SIGALRM assert triggered[1].f_code.co_name == "test_alarm2", triggered[1].f_code
def test_obj_return(self): """ Test that signal.signal returns a Python object if one is the current handler. """ from _signal import signal, SIGINT, SIG_DFL, SIG_IGN def installed(*a): pass try: for handler in SIG_DFL, SIG_IGN, lambda *a: None: signal(SIGINT, installed) assert signal(SIGINT, handler) is installed finally: signal(SIGINT, SIG_DFL)
def test_pep475_retry(self): import select, time import _signal as signal def foo(*args): signalled.append("ALARM") # a list of functions that will do nothing more than sleep for 3 # seconds cases = [(select.select, [], [], [], 3.0)] if hasattr(select, 'poll'): import posix poll = select.poll() cases.append((poll.poll, 3000)) # milliseconds if hasattr(select, 'epoll'): epoll = select.epoll() cases.append((epoll.poll, 3.0)) if hasattr(select, 'kqueue'): kqueue = select.kqueue() cases.append((kqueue.control, [], 1, 3.0)) if hasattr(select, 'devpoll'): raise NotImplementedError("write this test if we have devpoll") for wait_for_three_seconds in cases: print(wait_for_three_seconds[0]) signalled = [] signal.signal(signal.SIGALRM, foo) try: t1 = time.time() signal.alarm(1) wait_for_three_seconds[0](*wait_for_three_seconds[1:]) t2 = time.time() finally: signal.signal(signal.SIGALRM, signal.SIG_DFL) print("result: signalled = %r in %s seconds" % (signalled, t2 - t1)) assert signalled != [] assert t2 - t1 > 2.99
def test_alarm(self): try: from _signal import alarm, signal, SIG_DFL, SIGALRM except: skip('no alarm on this platform') import time l = [] def handler(*a): l.append(42) try: signal(SIGALRM, handler) alarm(1) time.sleep(2) assert l == [42] alarm(0) assert l == [42] finally: signal(SIGALRM, SIG_DFL)
def test_pep475_retry_sleep(self): import time import _signal as signal if not hasattr(signal, 'SIGALRM'): skip("SIGALRM available only under Unix") signalled = [] def foo(*args): signalled.append("ALARM") signal.signal(signal.SIGALRM, foo) try: t1 = time.time() signal.alarm(1) time.sleep(3.0) t2 = time.time() finally: signal.signal(signal.SIGALRM, signal.SIG_DFL) assert signalled != [] assert t2 - t1 > 2.99
def test_getsignal(self): """ Test that signal.getsignal returns the currently installed handler. """ from _signal import getsignal, signal, SIGINT, SIG_DFL, SIG_IGN def handler(*a): pass try: if not self.appdirect: assert getsignal(SIGINT) == SIG_DFL signal(SIGINT, SIG_DFL) assert getsignal(SIGINT) == SIG_DFL signal(SIGINT, SIG_IGN) assert getsignal(SIGINT) == SIG_IGN signal(SIGINT, handler) assert getsignal(SIGINT) is handler finally: signal(SIGINT, SIG_DFL)
def signal(signalnum, handler): handler = _signal.signal(_enum_to_int(signalnum), _enum_to_int(handler)) return _int_to_enum(handler, Handlers)
def run_command_line(interactive, inspect, run_command, no_site, run_module, run_stdin, warnoptions, unbuffered, ignore_environment, verbose, bytes_warning, quiet, isolated, dev_mode, **ignored): # with PyPy in top of CPython we can only have around 100 # but we need more in the PyPy level for the compiler package if not WE_ARE_TRANSLATED: sys.setrecursionlimit(5000) getenv = get_getenv() readenv = not ignore_environment io_encoding = getenv("PYTHONIOENCODING") if readenv else None initstdio(io_encoding, unbuffered) if 'faulthandler' in sys.builtin_module_names: if dev_mode or 'faulthandler' in sys._xoptions or ( readenv and getenv('PYTHONFAULTHANDLER')): import faulthandler try: faulthandler.enable(2) # manually set to stderr except ValueError: pass # ignore "2 is not a valid file descriptor" mainmodule = type(sys)('__main__') mainmodule.__loader__ = sys.__loader__ mainmodule.__builtins__ = __builtins__ mainmodule.__annotations__ = {} sys.modules['__main__'] = mainmodule if not no_site: # __PYVENV_LAUNCHER__, used here by CPython on macOS, is be ignored # since it (possibly) results in a wrong sys.prefix and # sys.exec_prefix (and consequently sys.path) set by site.py. try: import site except: print("'import site' failed", file=sys.stderr) # The priority order for warnings configuration is (highest precedence # first): # # - the BytesWarning filter, if needed ('-b', '-bb') # - any '-W' command line options; then # - the 'PYTHONWARNINGS' environment variable; then # - the dev mode filter ('-X dev', 'PYTHONDEVMODE'); then # - any implicit filters added by _warnings.c/warnings.py # # All settings except the last are passed to the warnings module via # the `sys.warnoptions` list. Since the warnings module works on the basis # of "the most recently added filter will be checked first", we add # the lowest precedence entries first so that later entries override them. sys_warnoptions = [] if dev_mode: sys_warnoptions.append("default") pythonwarnings = readenv and getenv('PYTHONWARNINGS') if pythonwarnings: sys_warnoptions.extend(pythonwarnings.split(',')) if warnoptions: sys_warnoptions.extend(warnoptions) if bytes_warning: sys_warnoptions.append("error::BytesWarning" if bytes_warning > 1 else "default::BytesWarning") if sys_warnoptions: sys.warnoptions[:] = sys_warnoptions try: if 'warnings' in sys.modules: from warnings import _processoptions _processoptions(sys.warnoptions) else: import warnings except ImportError as e: pass # CPython just eats any exception here # set up the Ctrl-C => KeyboardInterrupt signal handler, if the # signal module is available try: import _signal as signal except ImportError: pass else: signal.signal(signal.SIGINT, signal.default_int_handler) if hasattr(signal, "SIGPIPE"): signal.signal(signal.SIGPIPE, signal.SIG_IGN) if hasattr(signal, 'SIGXFZ'): signal.signal(signal.SIGXFZ, signal.SIG_IGN) if hasattr(signal, 'SIGXFSZ'): signal.signal(signal.SIGXFSZ, signal.SIG_IGN) def inspect_requested(): # We get an interactive prompt in one of the following three cases: # # * interactive=True, from the "-i" option # or # * inspect=True and stdin is a tty # or # * PYTHONINSPECT is set and stdin is a tty. # return (interactive or ((inspect or (readenv and getenv('PYTHONINSPECT'))) and sys.stdin.isatty())) success = True try: if run_command != 0: # handle the "-c" command # Put '' on sys.path try: bytes = run_command.encode() except BaseException as e: print("Unable to decode the command from the command line:", file=sys.stderr) display_exception(e) success = False else: if not isolated: sys.path.insert(0, '') success = run_toplevel(exec, bytes, mainmodule.__dict__) elif run_module != 0: # handle the "-m" command # '' on sys.path is required also here if not isolated: sys.path.insert(0, '') import runpy success = run_toplevel(runpy._run_module_as_main, run_module) elif run_stdin: # handle the case where no command/filename/module is specified # on the command-line. # update sys.path *after* loading site.py, in case there is a # "site.py" file in the script's directory. Only run this if we're # executing the interactive prompt, if we're running a script we # put it's directory on sys.path if not isolated: sys.path.insert(0, '') if interactive or sys.stdin.isatty(): # If stdin is a tty or if "-i" is specified, we print a # banner (unless "-q" was specified) and run # $PYTHONSTARTUP. if not quiet: print_banner(not no_site) python_startup = readenv and getenv('PYTHONSTARTUP') if python_startup: try: with open(python_startup, 'rb') as f: startup = f.read() except IOError as e: print("Could not open PYTHONSTARTUP", file=sys.stderr) print("IOError:", e, file=sys.stderr) else: @hidden_applevel def run_it(): co_python_startup = compile( startup, python_startup, 'exec', PyCF_ACCEPT_NULL_BYTES) exec(co_python_startup, mainmodule.__dict__) mainmodule.__file__ = python_startup mainmodule.__cached__ = None run_toplevel(run_it) try: del mainmodule.__file__ except (AttributeError, TypeError): pass # Then we need a prompt. inspect = True else: # If not interactive, just read and execute stdin normally. if verbose: print_banner(not no_site) @hidden_applevel def run_it(): co_stdin = compile(sys.stdin.read(), '<stdin>', 'exec', PyCF_ACCEPT_NULL_BYTES) exec(co_stdin, mainmodule.__dict__) mainmodule.__file__ = '<stdin>' mainmodule.__cached__ = None success = run_toplevel(run_it) else: # handle the common case where a filename is specified # on the command-line. filename = sys.argv[0] mainmodule.__file__ = filename mainmodule.__cached__ = None for hook in sys.path_hooks: try: importer = hook(filename) break except ImportError: continue else: importer = None if importer is None and not isolated: sys.path.insert(0, sys.pypy_resolvedirof(filename)) # assume it's a pyc file only if its name says so. # CPython goes to great lengths to detect other cases # of pyc file format, but I think it's ok not to care. try: from _frozen_importlib import (SourceFileLoader, SourcelessFileLoader) except ImportError: from _frozen_importlib_external import (SourceFileLoader, SourcelessFileLoader) if IS_WINDOWS: filename = filename.lower() if filename.endswith('.pyc'): # We don't actually load via SourcelessFileLoader # because '__main__' must not be listed inside # 'importlib._bootstrap._module_locks' (it deadlocks # test_multiprocessing_main_handling.test_script_compiled) from importlib._bootstrap_external import MAGIC_NUMBER import marshal loader = SourcelessFileLoader('__main__', filename) mainmodule.__loader__ = loader @hidden_applevel def execfile(filename, namespace): with open(filename, 'rb') as f: if f.read(4) != MAGIC_NUMBER: raise RuntimeError("Bad magic number in .pyc file") if len(f.read(8)) != 8: raise RuntimeError("Truncated .pyc file") co = marshal.load(f) if type(co) is not type((lambda: 0).__code__): raise RuntimeError("Bad code object in .pyc file") exec(co, namespace) args = (execfile, filename, mainmodule.__dict__) else: filename = sys.argv[0] if importer is not None: # It's the name of a directory or a zip file. # put the filename in sys.path[0] and import # the module __main__ import runpy sys.path.insert(0, filename) args = (runpy._run_module_as_main, '__main__', False) else: # That's the normal path, "pypy3 stuff.py". # We don't actually load via SourceFileLoader # because we require PyCF_ACCEPT_NULL_BYTES loader = SourceFileLoader('__main__', filename) mainmodule.__loader__ = loader @hidden_applevel def execfile(filename, namespace): with open(filename, 'rb') as f: code = f.read() co = compile(code, filename, 'exec', PyCF_ACCEPT_NULL_BYTES) exec(co, namespace) args = (execfile, filename, mainmodule.__dict__) success = run_toplevel(*args) except SystemExit as e: status = e.code if inspect_requested(): display_exception(e) else: status = not success # start a prompt if requested if inspect_requested(): try: from _pypy_interact import interactive_console if hasattr(sys, '__interactivehook__'): run_toplevel(sys.__interactivehook__) pypy_version_info = getattr(sys, 'pypy_version_info', sys.version_info) irc_topic = pypy_version_info[3] != 'final' or ( readenv and getenv('PYPY_IRC_TOPIC')) success = run_toplevel(interactive_console, mainmodule, quiet=quiet or not irc_topic) except SystemExit as e: status = e.code else: status = not success return status
def skip_test_alarm(): # (tfel): this test is very brittle, because it is supposed to work with our # first, very primitive implementation of signal handlers, which does not # allow Python code to run in the handler. So we rely on a side-effect on an # open file descriptor instead. try: import _signal except ImportError: import signal as _signal import posix import time import sys # first, we start opening files until the fd is the same as SIGALRM fds = [] dupd_fd = None fd = None try: fd = posix.open(__file__, posix.O_RDONLY) while fd < _signal.SIGALRM: fds.append(fd) fd = posix.open(__file__, posix.O_RDONLY) if fd > _signal.SIGALRM: dupd_fd = posix.dup(_signal.SIGALRM) posix.close(_signal.SIGALRM) fd = posix.open(__file__, posix.O_RDONLY) # close the unneeded fds for oldfd in fds: posix.close(oldfd) assert fd == _signal.SIGALRM, "fd not equal to SIGALRM" # temporary: graalpython doesn't check the argcount for the handler atm if sys.implementation.name == "graalpython": handler = posix.close else: handler = lambda s, f: posix.close(s) oldhandler = _signal.signal(_signal.SIGALRM, handler) assert oldhandler == _signal.SIG_DFL, "oldhandler != SIG_DFL" assert _signal.getsignal( _signal.SIGALRM) is handler, "getsignal handler != handler" # schedule the alarm signal, that will trigger the handler, which # will in turn close our file _signal.alarm(1) # wait for the signal to come in and be handled time.sleep(1.5) # check for the side-effect try: posix.read(fd, 1) except OSError: assert True else: assert False, "file is still open" finally: if dupd_fd is not None: try: posix.close(fd) except OSError: pass posix.dup(dupd_fd) # duplicates back into just free'd fd