我们从Python开源项目中,提取了以下50个代码示例,用于说明如何使用signal.set_wakeup_fd()。
def __init__(self, master=False): # Setup signal fd, this allows signal to behave correctly if os.name == 'posix': self.signal_pipe_r, self.signal_pipe_w = os.pipe() self._set_nonblock(self.signal_pipe_r) self._set_nonblock(self.signal_pipe_w) signal.set_wakeup_fd(self.signal_pipe_w) self._signals_received = collections.deque() signal.signal(signal.SIGINT, signal.SIG_DFL) if os.name == 'posix': signal.signal(signal.SIGCHLD, signal.SIG_DFL) signal.signal(signal.SIGTERM, self._signal_catcher) signal.signal(signal.SIGALRM, self._signal_catcher) signal.signal(signal.SIGHUP, self._signal_catcher) else: # currently a noop on window... signal.signal(signal.SIGTERM, self._signal_catcher) # FIXME(sileht): should allow to catch signal CTRL_BREAK_EVENT, # but we to create the child process with CREATE_NEW_PROCESS_GROUP # to make this work, so current this is a noop for later fix signal.signal(signal.SIGBREAK, self._signal_catcher)
def init_signals(self): # reset signaling [signal.signal(s, signal.SIG_DFL) for s in self.SIGNALS] # init new signaling signal.signal(signal.SIGQUIT, self.handle_quit) signal.signal(signal.SIGTERM, self.handle_exit) signal.signal(signal.SIGINT, self.handle_quit) signal.signal(signal.SIGWINCH, self.handle_winch) signal.signal(signal.SIGUSR1, self.handle_usr1) signal.signal(signal.SIGABRT, self.handle_abort) # Don't let SIGTERM and SIGUSR1 disturb active requests # by interrupting system calls if hasattr(signal, 'siginterrupt'): # python >= 2.6 signal.siginterrupt(signal.SIGTERM, False) signal.siginterrupt(signal.SIGUSR1, False) if hasattr(signal, 'set_wakeup_fd'): signal.set_wakeup_fd(self.PIPE[1])
def installHandler(fd): """ Install a signal handler which will write a byte to C{fd} when I{SIGCHLD} is received. This is implemented by installing a SIGCHLD handler that does nothing, setting the I{SIGCHLD} handler as not allowed to interrupt system calls, and using L{signal.set_wakeup_fd} to do the actual writing. @param fd: The file descriptor to which to write when I{SIGCHLD} is received. @type fd: C{int} """ if fd == -1: signal.signal(signal.SIGCHLD, signal.SIG_DFL) else: def noopSignalHandler(*args): pass signal.signal(signal.SIGCHLD, noopSignalHandler) signal.siginterrupt(signal.SIGCHLD, False) return signal.set_wakeup_fd(fd)
def init(cls): """ Creates a pipe for waking up a select call when a signal has been received. """ cls.__wake_up_pipe = os.pipe() fcntl.fcntl(cls.__wake_up_pipe[0], fcntl.F_SETFL, os.O_NONBLOCK) signal.set_wakeup_fd(EventQueueEmptyEventHandler.__wake_up_pipe[1]) # ------------------------------------------------------------------------------------------------------------------
def remove_signal_handler(self, sig): """Remove a handler for a signal. UNIX only. Return True if a signal handler was removed, False if not. """ self._check_signal(sig) try: del self._signal_handlers[sig] except KeyError: return False if sig == signal.SIGINT: handler = signal.default_int_handler else: handler = signal.SIG_DFL try: signal.signal(sig, handler) except OSError as exc: if exc.errno == errno.EINVAL: raise RuntimeError('sig {} cannot be caught'.format(sig)) else: raise if not self._signal_handlers: try: signal.set_wakeup_fd(-1) except (ValueError, OSError) as exc: logger.info('set_wakeup_fd(-1) failed: %s', exc) return True
def __init__(self): # https://msdn.microsoft.com/en-us/library/windows/desktop/aa363862(v=vs.85).aspx self._closed = True self._iocp = _check( kernel32. CreateIoCompletionPort(INVALID_HANDLE_VALUE, ffi.NULL, 0, 0) ) self._closed = False self._iocp_queue = deque() self._iocp_thread = None self._overlapped_waiters = {} self._completion_key_queues = {} # Completion key 0 is reserved for regular IO events self._completion_key_counter = itertools.count(1) # {stdlib socket object: task} # except that wakeup socket is mapped to None self._socket_waiters = {"read": {}, "write": {}} self._main_thread_waker = WakeupSocketpair() wakeup_sock = self._main_thread_waker.wakeup_sock self._socket_waiters["read"][wakeup_sock] = None # This is necessary to allow control-C to interrupt select(). # https://github.com/python-trio/trio/issues/42 if threading.current_thread() == threading.main_thread(): fileno = self._main_thread_waker.write_sock.fileno() self._old_signal_wakeup_fd = signal.set_wakeup_fd(fileno)
def close(self): if not self._closed: self._closed = True _check(kernel32.CloseHandle(self._iocp)) if self._iocp_thread is not None: self._iocp_thread.join() self._main_thread_waker.close() if threading.current_thread() == threading.main_thread(): signal.set_wakeup_fd(self._old_signal_wakeup_fd)
def _wait_forever(self): # Wait forever while True: # Check if signals have been received if os.name == "posix": self._empty_signal_pipe() self._run_signal_handlers() if os.name == "posix": # NOTE(sileht): we cannot use threading.Event().wait(), # threading.Thread().join(), or time.sleep() because signals # can be missed when received by non-main threads # (https://bugs.python.org/issue5315) # So we use select.select() alone, we will receive EINTR or # will read data from signal_r when signal is emitted and # cpython calls PyErr_CheckSignals() to run signals handlers # That looks perfect to ensure handlers are run and run in the # main thread try: select.select([self.signal_pipe_r], [], []) except select.error as e: if e.args[0] != errno.EINTR: raise else: # NOTE(sileht): here we do only best effort # and wake the loop periodically, set_wakeup_fd # doesn't work on non posix platform so # 1 seconds have been picked with the advice of a dice. time.sleep(1) # NOTE(sileht): We emulate SIGCHLD, _service_manager # will just check often for dead child self._signals_received.append(SIGCHLD)
def check_wakeup(self, test_body): # use a subprocess to have only one thread and to not change signal # handling of the parent process code = """if 1: import fcntl import os import signal def handler(signum, frame): pass {} signal.signal(signal.SIGALRM, handler) read, write = os.pipe() flags = fcntl.fcntl(write, fcntl.F_GETFL, 0) flags = flags | os.O_NONBLOCK fcntl.fcntl(write, fcntl.F_SETFL, flags) signal.set_wakeup_fd(write) test() os.close(read) os.close(write) """.format(test_body) assert_python_ok('-c', code)
def test_invalid_fd(self): fd = test_support.make_bad_fd() self.assertRaises(ValueError, signal.set_wakeup_fd, fd)
def setUp(self): import fcntl self.alrm = signal.signal(signal.SIGALRM, lambda x,y:None) self.read, self.write = os.pipe() flags = fcntl.fcntl(self.write, fcntl.F_GETFL, 0) flags = flags | os.O_NONBLOCK fcntl.fcntl(self.write, fcntl.F_SETFL, flags) self.old_wakeup = signal.set_wakeup_fd(self.write)
def tearDown(self): signal.set_wakeup_fd(self.old_wakeup) os.close(self.read) os.close(self.write) signal.signal(signal.SIGALRM, self.alrm)
def test_invalid_fd(self): fd = support.make_bad_fd() self.assertRaises(ValueError, signal.set_wakeup_fd, fd)
def check_wakeup(self, test_body, *signals, ordered=True): # use a subprocess to have only one thread code = """if 1: import fcntl import os import signal import struct signals = {!r} def handler(signum, frame): pass def check_signum(signals): data = os.read(read, len(signals)+1) raised = struct.unpack('%uB' % len(data), data) if not {!r}: raised = set(raised) signals = set(signals) if raised != signals: raise Exception("%r != %r" % (raised, signals)) {} signal.signal(signal.SIGALRM, handler) read, write = os.pipe() for fd in (read, write): flags = fcntl.fcntl(fd, fcntl.F_GETFL, 0) flags = flags | os.O_NONBLOCK fcntl.fcntl(fd, fcntl.F_SETFL, flags) signal.set_wakeup_fd(write) test() check_signum(signals) os.close(read) os.close(write) """.format(signals, ordered, test_body) assert_python_ok('-c', code)
def handle_sigchld(self, number, frame): """Apparently we need a sigchld handler to make set_wakeup_fd work.""" for task in self.running: if task.proc: task.proc.poll() # Apparently some UNIX systems automatically reset the SIGCHLD # handler to SIG_DFL. Reset it just in case. self.set_sigchld_handler()
def __init__(self): self.readmap = {} self.writemap = {} # Setup the wakeup file descriptor to avoid hanging on lost signals. wakeup_readfd, wakeup_writefd = os.pipe() fcntl.fcntl(wakeup_writefd, fcntl.F_SETFL, os.O_NONBLOCK) self.register_read(wakeup_readfd, self.wakeup_handler) signal.set_wakeup_fd(wakeup_writefd)
def _init_signals(self): self._signal_sets = defaultdict(list) self._default_signals = {} old_fd = signal.set_wakeup_fd(self._notify_sock.fileno()) assert old_fd < 0, 'Signals already initialized %d' % old_fd
def _shutdown_resources(self): log.debug('Kernel %r shutting down', self) if self._selector: self._selector.close() self._selector = None if self._notify_sock: self._notify_sock.close() self._notify_sock = None self._wait_sock.close() self._wait_sock = None if self._signal_sets: signal.set_wakeup_fd(-1) self._signal_sets = None self._default_signals = None if self._thread_pool: self._thread_pool.shutdown() self._thread_pool = None if self._process_pool: self._process_pool.shutdown() self._process_pool = None if self._monitor: self._monitor.close() # Main Kernel Loop # ----------
def add_signal_handler(self, sig, callback, *args): """Add a handler for a signal. UNIX only. Raise ValueError if the signal number is invalid or uncatchable. Raise RuntimeError if there is a problem setting up the handler. """ self._check_signal(sig) try: # set_wakeup_fd() raises ValueError if this is not the # main thread. By calling it early we ensure that an # event loop running in another thread cannot add a signal # handler. signal.set_wakeup_fd(self._csock.fileno()) except (ValueError, OSError) as exc: raise RuntimeError(str(exc)) handle = events.Handle(callback, args, self) self._signal_handlers[sig] = handle try: # Register a dummy signal handler to ask Python to write the signal # number in the wakup file descriptor. _process_self_data() will # read signal numbers from this file descriptor to handle signals. signal.signal(sig, _sighandler_noop) # Set SA_RESTART to limit EINTR occurrences. signal.siginterrupt(sig, False) except OSError as exc: del self._signal_handlers[sig] if not self._signal_handlers: try: signal.set_wakeup_fd(-1) except (ValueError, OSError) as nexc: logger.info('set_wakeup_fd(-1) failed: %s', nexc) if exc.errno == errno.EINVAL: raise RuntimeError('sig {} cannot be caught'.format(sig)) else: raise
def set_sigchld_handler(self): # TODO: find out whether set_wakeup_fd still works if the default # signal handler is used (I'm pretty sure it doesn't work if the # signal is ignored). signal.signal(signal.SIGCHLD, self.handle_sigchld) # This should keep reads and writes from getting EINTR. if hasattr(signal, 'siginterrupt'): signal.siginterrupt(signal.SIGCHLD, False)
def handle_sigchld(self, number, frame): """Apparently we need a sigchld handler to make set_wakeup_fd work.""" # Write to the signal pipe (only for Python <2.5, where the # set_wakeup_fd method doesn't exist). if self.iomap.wakeup_writefd: os.write(self.iomap.wakeup_writefd, '\0') for task in self.running: if task.proc: task.proc.poll() # Apparently some UNIX systems automatically reset the SIGCHLD # handler to SIG_DFL. Reset it just in case. self.set_sigchld_handler()
def __init__(self): self.readmap = {} self.writemap = {} # Setup the wakeup file descriptor to avoid hanging on lost signals. wakeup_readfd, wakeup_writefd = os.pipe() self.register_read(wakeup_readfd, self.wakeup_handler) # TODO: remove test when we stop supporting Python <2.5 if hasattr(signal, 'set_wakeup_fd'): signal.set_wakeup_fd(wakeup_writefd) self.wakeup_writefd = None else: self.wakeup_writefd = wakeup_writefd
def add_signal_handler(self, sig, callback, *args): """Add a handler for a signal. UNIX only. Raise ValueError if the signal number is invalid or uncatchable. Raise RuntimeError if there is a problem setting up the handler. """ if (coroutines.iscoroutine(callback) or coroutines.iscoroutinefunction(callback)): raise TypeError("coroutines cannot be used " "with add_signal_handler()") self._check_signal(sig) self._check_closed() try: # set_wakeup_fd() raises ValueError if this is not the # main thread. By calling it early we ensure that an # event loop running in another thread cannot add a signal # handler. signal.set_wakeup_fd(self._csock.fileno()) except (ValueError, OSError) as exc: raise RuntimeError(str(exc)) handle = events.Handle(callback, args, self) self._signal_handlers[sig] = handle try: # Register a dummy signal handler to ask Python to write the signal # number in the wakup file descriptor. _process_self_data() will # read signal numbers from this file descriptor to handle signals. signal.signal(sig, _sighandler_noop) # Set SA_RESTART to limit EINTR occurrences. signal.siginterrupt(sig, False) except OSError as exc: del self._signal_handlers[sig] if not self._signal_handlers: try: signal.set_wakeup_fd(-1) except (ValueError, OSError) as nexc: logger.info('set_wakeup_fd(-1) failed: %s', nexc) if exc.errno == errno.EINVAL: raise RuntimeError('sig {} cannot be caught'.format(sig)) else: raise
def main(): writer, reader = socket.socketpair() writer.setblocking(False) reader.setblocking(False) signal.set_wakeup_fd(writer.fileno()) # Keep trying until we lose the race... for attempt in itertools.count(): print(f"Attempt {attempt}: start") # Make sure the socket is empty drained = drain(reader) if drained: print(f"Attempt {attempt}: ({drained} residual bytes discarded)") # Arrange for SIGINT to be delivered 1 second from now thread = threading.Thread(target=raise_SIGINT_soon) thread.start() # Fake an IO loop that's trying to sleep for 10 seconds (but will # hopefully get interrupted after just 1 second) start = time.monotonic() target = start + 10 try: select_calls = 0 drained = 0 while True: now = time.monotonic() if now > target: break select_calls += 1 r, _, _ = select.select([reader], [], [], target - now) if r: # In theory we should loop to fully drain the socket but # honestly there's 1 byte in there at most and it'll be # fine. drained += drain(reader) except KeyboardInterrupt: pass else: print(f"Attempt {attempt}: no KeyboardInterrupt?!") # We expect a successful run to take 1 second, and a failed run to # take 10 seconds, so 2 seconds is a reasonable cutoff to distinguish # them. duration = time.monotonic() - start if duration < 2: print(f"Attempt {attempt}: OK, trying again " f"(select_calls = {select_calls}, drained = {drained})") else: print(f"Attempt {attempt}: FAILED, took {duration} seconds") print(f"select_calls = {select_calls}, drained = {drained}") break thread.join()