def run(self): child_fd = signalfd.signalfd(0, [signal.SIGCHLD], signalfd.SFD_NONBLOCK|signalfd.SFD_CLOEXEC) with os.fdopen(child_fd, 'rb') as child_signals: signalfd.sigprocmask(signalfd.SIG_BLOCK, [signal.SIGCHLD]) with closing(cloexec(socket.socket(socket.AF_UNIX, socket.SOCK_STREAM))) as requests_sock: if os.path.exists(self.socket_name): os.unlink(self.socket_name) requests_sock.bind(self.socket_name) requests_sock.listen(self.socket_backlog) try: while 1: qlen = len(self.queues) logger.debug("Queues => %s workspaces", qlen) for i, wq in enumerate(self.queues.values()): if i + 1 == qlen: logger.debug(" \_ %s", wq) else: logger.debug(" |_ %s", wq) current_fds = [child_fd, requests_sock] current_fds.extend(self.clients.keys()) read_ready, _, errors = select.select(current_fds, [], current_fds, 1) for fd in read_ready: if requests_sock == fd: self.handle_accept(requests_sock) elif fd in self.clients: self.handle_request(fd) elif fd == child_fd: self.handle_signal(child_signals) for fd in errors: logger.error("Fd %r has error !", fd) finally: for fd, (fh, _) in self.clients.items(): close(fh, fd)
def test_read_fd_no_data(): fd = signalfd.signalfd(-1, [signal.SIGUSR1], signalfd.SFD_CLOEXEC | signalfd.SFD_NONBLOCK) try: err = pytest.raises((OSError, IOError), signalfd.read_siginfo, fd) assert err.value.errno == errno.EAGAIN finally: os.close(fd)
def test_read_fh_no_data(): fd = signalfd.signalfd(-1, [signal.SIGUSR1], signalfd.SFD_CLOEXEC | signalfd.SFD_NONBLOCK) fh = os.fdopen(fd, 'rb') try: err = pytest.raises((OSError, IOError), signalfd.read_siginfo, fh) assert err.value.errno == errno.EAGAIN finally: fh.close()
def signalfd(self, *a, **kw): try: return signalfd.signalfd(*a, **kw) except OSError: type, value, traceback = sys.exc_info() if value.errno == errno.ENOSYS: raise unittest.Skip( "signalfd() not implemented on this platform")
def test_block_and_read(): fd = signalfd.signalfd(-1, [signal.SIGUSR1], signalfd.SFD_CLOEXEC) try: signalfd.sigprocmask(signalfd.SIG_BLOCK, [signal.SIGUSR1]) os.kill(os.getpid(), signal.SIGUSR1) si = signalfd.read_siginfo(fd) assert si.ssi_signo == signal.SIGUSR1 finally: os.close(fd)
def run(self): child_fd = signalfd.signalfd( -1, [signal.SIGCHLD], signalfd.SFD_NONBLOCK | signalfd.SFD_CLOEXEC) with os.fdopen(child_fd, "rb") as child_signals: signalfd.sigprocmask(signalfd.SIG_BLOCK, [signal.SIGCHLD]) with closing( cloexec(socket.socket( socket.AF_UNIX, socket.SOCK_STREAM))) as requests_sock: logger.info("Binding to %r", self.socket_path) if os.path.exists(self.socket_path): os.unlink(self.socket_path) pending_socket_path = "%s-pending" % self.socket_path requests_sock.bind(pending_socket_path) requests_sock.listen(self.socket_backlog) os.rename(pending_socket_path, self.socket_path) try: while 1: qlen = len(self.queues) logger.debug("Queues => %s workspaces", qlen) for i, wq in enumerate(self.queues.values()): if i + 1 == qlen: logger.debug(" \_ %s", wq) else: logger.debug(" |_ %s", wq) current_fds = [child_fd, requests_sock] current_fds.extend(self.clients.keys()) read_ready, _, errors = select.select( current_fds, [], current_fds, 1) for fd in read_ready: if requests_sock == fd: self.handle_accept(requests_sock) elif fd in self.clients: self.handle_request(fd) elif fd == child_fd: self.handle_signal(child_signals) for fd in errors: logger.error("Fd %r has error !", fd) finally: for fd, (fh, _) in self.clients.items(): close(fh, fd)
def run_server(args): """ It is important that we create the signal FD and block the signals before doing anything else. Otherwise, we may get interrupted partway during initialization, and the resources we have allocated thus far will not be released. """ sig_fd = signalfd.signalfd(-1, shutdown_signals, SFD_NONBLOCK | SFD_CLOEXEC) signalfd.sigprocmask(SIG_BLOCK, shutdown_signals) sock, epoll = None, None conn_dict = {} try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setblocking(False) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.bind(('0.0.0.0', SERVER_PORT)) epoll = select.epoll(sizehint=2, flags=EPOLL_CLOEXEC) epoll.register(sig_fd, EPOLLIN) epoll.register(sock, EPOLLIN) sock.listen(SERVER_BACKLOG_SIZE) print("Listening on {}:{}.".format(socket.gethostname(), SERVER_PORT), file=sys.stderr, flush=True) listen(sock, sig_fd, conn_dict, epoll) except SystemExit: print("Terminated.", file=sys.stderr, flush=True) raise finally: if epoll: epoll.close() os.close(sig_fd) if sock: close_socket(sock) for conn, _ in conn_dict.values(): close_socket(conn)
def start(self, loglevel, logfile): """Start to work !""" logging.basicConfig( level=loglevel, stream=logfile, format= "%(levelname)s|%(asctime)s|%(process)d|%(filename)s|%(funcName)s|%(lineno)d| %(message)s" ) global _LOGGER _LOGGER = logging.getLogger(__name__) self.init_sockets() _LOGGER.info("Worker %d started", self.worker_id) fd = signalfd.signalfd(-1, [signal.SIGTERM], signalfd.SFD_CLOEXEC) signalfd.sigprocmask(signalfd.SIG_BLOCK, [signal.SIGTERM]) with os.fdopen(fd) as fo: poller = zmq.Poller() poller.register(self.rep_sock, zmq.POLLIN) poller.register(fo, zmq.POLLIN) while True: try: items = dict(poller.poll(1000)) if self.rep_sock in items: cmd = self.rep_sock.recv() _LOGGER.debug("cmd received from client: '%s'", cmd) self.process_cmd(cmd) _LOGGER.debug("cmd '%s' processed", cmd) if fo.fileno() in items: _LOGGER.debug("Signal received on worker %d", self.worker_id) break except KeyboardInterrupt: _LOGGER.debug("Keyboard interrrupt received on worker %d", self.worker_id) break _LOGGER.debug("Stopping worker %d", self.worker_id) self.rep_sock.close()
for i in range(TIMEOUT * 100): time.sleep(0.1) elif test_name == 'test_oneshot_on_usr2': manhole.install(oneshot_on='USR2') for i in range(TIMEOUT * 100): time.sleep(0.1) elif test_name.startswith('test_signalfd_weirdness'): if 'negative' in test_name: manhole.install(sigmask=None) else: manhole.install(sigmask=[signal.SIGCHLD]) time.sleep(0.3) # give the manhole a bit enough time to start print('Starting ...') import signalfd signalfd.sigprocmask(signalfd.SIG_BLOCK, [signal.SIGCHLD]) fd = signalfd.signalfd(0, [signal.SIGCHLD], signalfd.SFD_NONBLOCK|signalfd.SFD_CLOEXEC) for i in range(200): print('Forking %s:' % i) pid = os.fork() print(' - [%s/%s] forked' % (i, pid)) if pid: while 1: print(' - [%s/%s] selecting on: %s' % (i, pid, [fd])) read_ready, _, errors = select.select([fd], [], [fd], 1) if read_ready: try: print(' - [%s/%s] reading from signalfd ...' % (i, pid)) print(' - [%s] read from signalfd: %r ' % (i, os.read(fd, 128))) break except OSError as exc: print(' - [%s/%s] reading from signalfd failed with errno %s' % (i, pid, exc.errno))
def __init__(self, mask = [signal.SIGCHLD, signal.SIGTSTP]): self.mask = mask self.signal_handlers = {} IOHandler.__init__(self, signalfd.signalfd(-1, mask, signalfd.SFD_CLOEXEC | signalfd.SFD_NONBLOCK), usage="SignalManager") signalfd.sigprocmask(signalfd.SIG_BLOCK, mask)
import os import sys import signal import select from signalfd import signalfd, sigset # Create a signal set containing all signals. mask = sigset() mask.fill() with signalfd(mask) as fd: poll = select.poll() poll.register(fd, select.POLLIN) poll.register(sys.stdin, select.POLLIN) # Print signals as they are received until user presses <RETURN>. print '=' * 70 print 'Send signals to this process (%d) or press RETURN to exit.' % os.getpid() print '=' * 70 while True: events = dict(poll.poll()) if fd.fileno() in events: info = fd.info() print 'received signal %d' % info.ssi_signo if sys.stdin.fileno() in events: print 'all done' break
def __init__(self, mask = [signal.SIGCHLD]): self.mask = mask self.signal_handlers = {} IOHandler.__init__(self, signalfd.signalfd(-1, mask, signalfd.SFD_CLOEXEC | signalfd.SFD_NONBLOCK), usage="SignalManager") signalfd.sigprocmask(signalfd.SIG_BLOCK, mask)
def test_read_closed(): fd = signalfd.signalfd(-1, [signal.SIGUSR1], signalfd.SFD_CLOEXEC) os.close(fd) pytest.raises(OSError, signalfd.read_siginfo, fd)
for i in range(TIMEOUT * 100): time.sleep(0.1) elif test_name == 'test_oneshot_on_usr2': manhole.install(oneshot_on='USR2') for i in range(TIMEOUT * 100): time.sleep(0.1) elif test_name.startswith('test_signalfd_weirdness'): if 'negative' in test_name: manhole.install(sigmask=None) else: manhole.install(sigmask=[signal.SIGCHLD]) print('Starting ...') import signalfd signalfd.sigprocmask(signalfd.SIG_BLOCK, [signal.SIGCHLD]) fd = signalfd.signalfd( 0, [signal.SIGCHLD], signalfd.SFD_NONBLOCK | signalfd.SFD_CLOEXEC) for i in range(200): print('Forking %s:' % i) pid = os.fork() print(' - [%s/%s] forked' % (i, pid)) if pid: while 1: print(' - [%s/%s] selecting on: %s' % (i, pid, [fd])) read_ready, _, errors = select.select([fd], [], [fd], 1) if read_ready: try: print(' - [%s/%s] reading from signalfd ...' % (i, pid)) print(' - [%s] read from signalfd: %r ' %