コード例 #1
0
    def run(self):
        """
        Runs the manhole loop. Only accepts one connection at a time because:

        * This thread is a daemon thread (exits when main thread exists).
        * The connection need exclusive access to stdin, stderr and stdout so it can redirect inputs and outputs.
        """
        self.serious.set()
        if signalfd and self.sigmask:
            signalfd.sigprocmask(signalfd.SIG_BLOCK, self.sigmask)
        pthread_setname_np(self.ident, self.name)

        if self.bind_delay:
            _LOG("Delaying UDS binding %s seconds ..." % self.bind_delay)
            _ORIGINAL_SLEEP(self.bind_delay)

        sock = self.get_socket()
        while self.should_run:
            _LOG("Waiting for new connection (in pid:%s) ..." % os.getpid())
            try:
                client = ManholeConnectionThread(sock.accept()[0],
                                                 self.connection_handler,
                                                 self.daemon_connection)
                client.start()
                client.join()
            except (InterruptedError, socket.error) as e:
                if e.errno != errno.EINTR:
                    raise
                continue
            finally:
                client = None
コード例 #2
0
 def test_return_previous_mask(self):
     """
     sigprocmask returns a list of the signals previously masked.
     """
     previous = signalfd.sigprocmask(signalfd.SIG_BLOCK, [1, 3, 5])
     result = signalfd.sigprocmask(signalfd.SIG_BLOCK, previous)
     self.assertEquals(result, [1, 3, 5])
コード例 #3
0
    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)
コード例 #4
0
ファイル: manhole.py プロジェクト: nirs/python-manhole
    def run(self):
        """
        Runs the manhole loop. Only accepts one connection at a time because:

        * This thread is a daemon thread (exits when main thread exists).
        * The connection need exclusive access to stdin, stderr and stdout so it can redirect inputs and outputs.
        """
        self.serious.set()
        if signalfd and self.sigmask:
            signalfd.sigprocmask(signalfd.SIG_BLOCK, self.sigmask)
        pthread_setname_np(self.ident, self.name)

        if self.bind_delay:
            _cry("Delaying UDS binding %s seconds ..." % self.bind_delay)
            _ORIGINAL_SLEEP(self.bind_delay)

        sock = self.get_socket()
        while True:
            _cry("Waiting for new connection (in pid:%s) ..." % os.getpid())
            try:
                client = ManholeConnection(sock.accept()[0], self.locals, self.daemon_connection)
                client.start()
                client.join()
            except (InterruptedError, socket.error) as e:
                if e.errno != errno.EINTR:
                    raise
                continue
            finally:
                client = None
コード例 #5
0
ファイル: manhole.py プロジェクト: vmarkovtsev/veles
    def run(self):
        cry('Started ManholeConnection thread. Checking credentials ...')
        if signalfd and self.sigmask:
            signalfd.sigprocmask(signalfd.SIG_BLOCK, self.sigmask)
        pthread_setname_np(self.ident, "Manhole ----")

        pid, _, _ = self.check_credentials(self.client)
        pthread_setname_np(self.ident, "Manhole %s" % pid)
        self.handle(self.client)
コード例 #6
0
ファイル: manhole.py プロジェクト: 2php/veles
    def run(self):
        cry('Started ManholeConnection thread. Checking credentials ...')
        if signalfd and self.sigmask:
            signalfd.sigprocmask(signalfd.SIG_BLOCK, self.sigmask)
        pthread_setname_np(self.ident, "Manhole ----")

        pid, _, _ = self.check_credentials(self.client)
        pthread_setname_np(self.ident, "Manhole %s" % pid)
        self.handle(self.client)
コード例 #7
0
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)
コード例 #8
0
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)
コード例 #9
0
 def test_invalid_how(self):
     """
     If a value other than SIG_BLOCK, SIG_UNBLOCK, or SIG_SETMASK is passed
     for the how argument to sigprocmask, ValueError is raised.
     """
     message = "value specified for how (1700) invalid"
     try:
         signalfd.sigprocmask(1700, [])
     except ValueError:
         type, value, traceback = sys.exc_info()
         self.assertEquals(str(value), message)
コード例 #10
0
 def test_invalid_signal(self):
     """
     If an object in the iterable passed for the signals parameter to
     sigprocmask isn't an integer, TypeError is raised.
     """
     try:
         signalfd.sigprocmask(signalfd.SIG_BLOCK, [object()])
     except TypeError:
         type, value, traceback = sys.exc_info()
         self.assertEquals(str(value), "an integer is required")
     else:
         self.fail(
             "Expected non-integer signal to be rejected.")
コード例 #11
0
 def test_invalid_signal_iterable(self):
     """
     If iterating over the value passed for the signals parameter to
     sigprocmask raises an exception, sigprocmask raises that exception.
     """
     class BrokenIter(object):
         def __iter__(self):
             raise RuntimeError("my __iter__ is broken")
     try:
         signalfd.sigprocmask(signalfd.SIG_BLOCK, BrokenIter())
     except RuntimeError:
         type, value, traceback = sys.exc_info()
         self.assertEquals(str(value), "my __iter__ is broken")
コード例 #12
0
 def __init__(self, gdb_id):
   # Workaround -----------------------------------------------------------------
   # We need this as a workaround for the bug in GDB: https://sourceware.org/bugzilla/show_bug.cgi?id=17314
   # This is based in the fix done in GDB for Guile in this patch: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=patch;h=92d8d229d9a310ebfcfc13bf4a75a286c1add1ac
   import signal
   previous_mask = signalfd.sigprocmask(signalfd.SIG_BLOCK, [signal.SIGCHLD, signal.SIGCONT, signal.SIGINT])
   try:
       EH.__init__(self, name="(gdb %s[plugin])" % gdb_id, as_daemon=True) # as_daemon=True otherwise GDB hangs
   finally:
       signalfd.sigprocmask(signalfd.SIG_SETMASK, previous_mask) # restore the mask for GDB
   # ----------------------------------------------------------------------------
       
   self.gdb_id = gdb_id
   self.queue = Queue.Queue(maxsize=1000000)
コード例 #13
0
 def test_block(self):
     """
     When invoked with SIG_BLOCK, sigprocmask blocks the signals in the
     sigmask list.
     """
     self._handle_sigusr1()
     previous = signalfd.sigprocmask(signalfd.SIG_BLOCK, [signal.SIGUSR1])
     os.kill(os.getpid(), signal.SIGUSR1)
     try:
         # Expect to receive SIGUSR1 after unblocking it.
         signalfd.sigprocmask(signalfd.SIG_SETMASK, previous)
     except SomeException:
         pass
     else:
         self.fail(
             "Expected exception to be raised after unblocking SIGUSR1")
コード例 #14
0
    def test_unblock(self):
        """
        When invoked with SIG_UNBLOCK, sigprocmask unblocks the signals in the
        sigmask list.
        """
        self._handle_sigusr1()
        previous = signalfd.sigprocmask(signalfd.SIG_BLOCK, [signal.SIGUSR1])
        self.addCleanup(signalfd.sigprocmask, signalfd.SIG_SETMASK, previous)
        signalfd.sigprocmask(signalfd.SIG_UNBLOCK, [signal.SIGUSR1])

        try:
            os.kill(os.getpid(), signal.SIGUSR1)
        except SomeException:
            pass
        else:
            self.fail(
                "Expected SIGUSR1 to trigger handler raising SomeException")
コード例 #15
0
ファイル: manhole.py プロジェクト: 2php/veles
    def run(self):
        self.serious.set()
        if signalfd and self.sigmask:
            signalfd.sigprocmask(signalfd.SIG_BLOCK, self.sigmask)
        pthread_setname_np(self.ident, self.name)

        sock, pid = self.get_socket()
        while True:
            cry("Waiting for a new connection (in pid %s) ..." % pid)
            try:
                client = ManholeConnection(sock.accept()[0], self.sigmask)
                client.start()
                client.join()
            except (InterruptedError, socket.error) as e:
                if e.errno != errno.EINTR:
                    raise
                continue
            finally:
                client = None
コード例 #16
0
ファイル: manhole.py プロジェクト: vmarkovtsev/veles
    def run(self):
        self.serious.set()
        if signalfd and self.sigmask:
            signalfd.sigprocmask(signalfd.SIG_BLOCK, self.sigmask)
        pthread_setname_np(self.ident, self.name)

        sock, pid = self.get_socket()
        while True:
            cry("Waiting for a new connection (in pid %s) ..." % pid)
            try:
                client = ManholeConnection(sock.accept()[0], self.sigmask)
                client.start()
                client.join()
            except (InterruptedError, socket.error) as e:
                if e.errno != errno.EINTR:
                    raise
                continue
            finally:
                client = None
コード例 #17
0
ファイル: worker.py プロジェクト: obestwalter/python-stampede
    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)
コード例 #18
0
 def test_handle_signals(self):
     """
     After signalfd is called, if a signal is received which was in the
     sigmask list passed to that call, information about the signal can be
     read from the fd returned by that call.
     """
     fd = self.signalfd(-1, [signal.SIGUSR2])
     self.addCleanup(os.close, fd)
     previous = signalfd.sigprocmask(signalfd.SIG_BLOCK, [signal.SIGUSR2])
     self.addCleanup(signalfd.sigprocmask, signalfd.SIG_SETMASK, previous)
     os.kill(os.getpid(), signal.SIGUSR2)
     bytes = os.read(fd, 128)
     self.assertTrue(bytes)
コード例 #19
0
    def _handle_sigusr1(self):
        old_handler = signal.signal(signal.SIGUSR1, raiser)
        self.addCleanup(signal.signal, signal.SIGUSR1, old_handler)

        # This depends on sigprocmask working a bit.  If it doesn't, then
        # this won't succeed in keeping the signal mask state sane.  But
        # there's nothing else we can do in that case.  This is necessary at
        # all because some environments start off with certain signals
        # masked for obscure reasons.  The intent is to provide the tests
        # with a consistent, predictable starting state and then restore the
        # environment's expectations after the test.
        old_mask = signalfd.sigprocmask(signalfd.SIG_SETMASK, [])
        self.addCleanup(signalfd.sigprocmask, signalfd.SIG_SETMASK, old_mask)
コード例 #20
0
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)
コード例 #21
0
 def test_read_signals(self):
     """
     signalfd.read_signalfd should behave like test_handle_signals but
     return a SigInfo instance instead of raw bytes
     """
     fd = self.signalfd(-1, [signal.SIGUSR2])
     self.addCleanup(os.close, fd)
     previous = signalfd.sigprocmask(signalfd.SIG_BLOCK, [signal.SIGUSR2])
     self.addCleanup(signalfd.sigprocmask, signalfd.SIG_SETMASK, previous)
     os.kill(os.getpid(), signal.SIGUSR2)
     siginfo = signalfd.read_signalfd(fd)
     self.assertTrue(siginfo)
     self.assertEqual(siginfo.ssi_signo, signal.SIGUSR2)
     self.assertEqual(siginfo.ssi_pid, os.getpid())
コード例 #22
0
 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()
コード例 #23
0
     print("Sending signal to manhole thread ...")
     pthread_kill(manhole._INST.ident, signal.SIGUSR2)
     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 ...' %
コード例 #24
0
ファイル: helper.py プロジェクト: nirs/python-manhole
     pthread_kill(manhole._INST.ident, signal.SIGUSR2)
     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:
コード例 #25
0
            @partial(signal.signal, signal.SIGUSR1)
            def signal_handler(sig, _):
                print('Received signal %s' % sig)
                global signalled
                signalled = True

            if 'negative' in test_name:
                manhole.install(sigmask=None)
            else:
                manhole.install(sigmask=[signal.SIGUSR1])

            time.sleep(0.3)  # give the manhole a bit enough time to start
            print('Starting ...')
            import signalfd

            signalfd.sigprocmask(signalfd.SIG_BLOCK, [signal.SIGUSR1])
            sys.setcheckinterval(1)
            for i in range(100000):
                os.kill(os.getpid(), signal.SIGUSR1)
            print('signalled=%s' % signalled)
            time.sleep(TIMEOUT * 10)
        elif test_name == 'test_auth_fail':
            manhole.get_peercred = lambda _: (-1, -1, -1)
            manhole.install()
            time.sleep(TIMEOUT * 10)
        elif test_name == 'test_socket_path':
            manhole.install(socket_path=SOCKET_PATH)
            time.sleep(TIMEOUT * 10)
        elif test_name == 'test_daemon_connection':
            manhole.install(daemon_connection=True)
            time.sleep(TIMEOUT)
コード例 #26
0
ファイル: helper.py プロジェクト: ionelmc/python-manhole
            @partial(signal.signal, signal.SIGUSR1)
            def signal_handler(sig, _):
                print('Received signal %s' % sig)
                global signalled
                signalled = True

            if 'negative' in test_name:
                manhole.install(sigmask=None)
            else:
                manhole.install(sigmask=[signal.SIGUSR1])

            time.sleep(0.3)  # give the manhole a bit enough time to start
            print('Starting ...')
            import signalfd

            signalfd.sigprocmask(signalfd.SIG_BLOCK, [signal.SIGUSR1])
            sys.setcheckinterval(1)
            for i in range(100000):
                os.kill(os.getpid(), signal.SIGUSR1)
            print('signalled=%s' % signalled)
            time.sleep(TIMEOUT * 10)
        elif test_name == 'test_auth_fail':
            manhole.get_peercred = lambda _: (-1, -1, -1)
            manhole.install()
            time.sleep(TIMEOUT * 10)
        elif test_name == 'test_socket_path':
            manhole.install(socket_path=SOCKET_PATH)
            time.sleep(TIMEOUT * 10)
        elif test_name == 'test_daemon_connection':
            manhole.install(daemon_connection=True)
            time.sleep(TIMEOUT)
コード例 #27
0
ファイル: iterio.py プロジェクト: redhog/pieshell
 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)
コード例 #28
0
ファイル: iterio.py プロジェクト: Mechachleopteryx/pieshell
 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)