Example #1
0
    def _shutdown_resources(self):
        log.debug("Kernel %r shutting down", self)
        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._selector:
            self._selector.close()
            self._selector = 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()
Example #2
0
    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
Example #3
0
def main():
    pipe_r, pipe_w = os.pipe()
    flags = fcntl.fcntl(pipe_w, fcntl.F_GETFL, 0)
    flags = flags | os.O_NONBLOCK
    fcntl.fcntl(pipe_w, fcntl.F_SETFL, flags)
    
    signal.signal(signal.SIGCHLD, lambda x,y: None)
    signal.signal(signal.SIGALRM, lambda x,y: None)
    signal.siginterrupt(signal.SIGCHLD,False) #makes no difference
    signal.siginterrupt(signal.SIGALRM,False) #makes no difference
    signal.set_wakeup_fd(pipe_w)
    signal.setitimer(signal.ITIMER_REAL, 2, 2)
    
    poller = select.epoll()
    poller.register(pipe_r, select.EPOLLIN)
    poller.register(sys.stdin, select.EPOLLIN)
    
    print "Main screen turn on"
    while True:
        events=[]
        try:
            events = poller.poll()
            try:
                for fd, flags in events:
                    ch=os.read(fd, 1)
                    if fd==pipe_r:
                        sys.stdout.write( "We get Signal" )
                    if fd==sys.stdin.fileno():
                        sys.stdout.write( ch )
                    sys.stdout.flush()
            except IOError as e:
                print "exception loop" + str(e)
        except IOError as e:
            print "exception poll" + str(e)
Example #4
0
    def _setup_signals(self):
        """Set up signal handlers.

        On Windows this uses a QTimer to periodically hand control over to
        Python so it can handle signals.

        On Unix, it uses a QSocketNotifier with os.set_wakeup_fd to get
        notified.
        """
        signal.signal(signal.SIGINT, self.interrupt)
        signal.signal(signal.SIGTERM, self.interrupt)

        if os.name == 'posix' and hasattr(signal, 'set_wakeup_fd'):
            import fcntl
            read_fd, write_fd = os.pipe()
            for fd in (read_fd, write_fd):
                flags = fcntl.fcntl(fd, fcntl.F_GETFL)
                fcntl.fcntl(fd, fcntl.F_SETFL, flags | os.O_NONBLOCK)
            self._signal_notifier = QSocketNotifier(
                read_fd, QSocketNotifier.Read, self)
            self._signal_notifier.activated.connect(self._handle_signal_wakeup)
            signal.set_wakeup_fd(write_fd)
        else:
            self._signal_timer = usertypes.Timer(self, 'python_hacks')
            self._signal_timer.start(1000)
            self._signal_timer.timeout.connect(lambda: None)
Example #5
0
    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:
            if compat.PY33:
                # On Python 3.3 and newer, the C signal handler writes the
                # signal number into the wakeup file descriptor and then calls
                # Py_AddPendingCall() to schedule the Python signal handler.
                #
                # Register a dummy signal handler to ask Python to write the
                # signal number into the wakup file descriptor.
                # _process_self_data() will read signal numbers from this file
                # descriptor to handle signals.
                signal.signal(sig, _sighandler_noop)
            else:
                # On Python 3.2 and older, the C signal handler first calls
                # Py_AddPendingCall() to schedule the Python signal handler,
                # and then write a null byte into the wakeup file descriptor.
                signal.signal(sig, self._handle_signal)

            # Set SA_RESTART to limit EINTR occurrences.
            signal.siginterrupt(sig, False)
        except (RuntimeError, OSError) as exc:
            # On Python 2, signal.signal(signal.SIGKILL, signal.SIG_IGN) raises
            # RuntimeError(22, 'Invalid argument'). On Python 3,
            # OSError(22, 'Invalid argument') is raised instead.
            exc_type, exc_value, tb = sys.exc_info()

            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 isinstance(exc, RuntimeError) or exc.errno == errno.EINVAL:
                raise RuntimeError('sig {0} cannot be caught'.format(sig))
            else:
                reraise(exc_type, exc_value, tb)
Example #6
0
        def _shutdown():
            nonlocal njobs
            for task in sorted(tasks.values(), key=lambda t: t.id, reverse=True):
                if task.id == self._kernel_task_id:
                    continue

                # If the task is daemonic, force it to non-daemon status and cancel it
                if task.daemon:
                    njobs += 1
                    task.daemon = False

                assert _cancel_task(task)

            # Run all of the daemon tasks through cancellation
            if ready:
                self.run()

            # Cancel the kernel loopback task (if any)
            task = tasks.pop(self._kernel_task_id, None)
            if task:
                task.cancel_func()
                self._notify_sock.close()
                self._notify_sock = None
                self._wait_sock.close()
                self._wait_sock = None
                self._kernel_task_id = None

            # Remove the signal handling file descriptor (if any)
            if self._signal_sets:
                signal.set_wakeup_fd(-1)
                self._signal_sets = None
                self._default_signals = None
Example #7
0
    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 as exc:
            raise RuntimeError(str(exc))

        handle = events.make_handle(callback, args)
        self._signal_handlers[sig] = handle

        try:
            signal.signal(sig, self._handle_signal)
            # 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 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
Example #8
0
def register():
    '''
    This function creates a select.poll object that can be used in the same
    manner as signal.pause(). The poll object returns each time a signal was
    received by the process.

    This function has to be called from the main thread.
    '''

    global _signal_poller
    global _signal_read_fd

    if _signal_poller is not None:
        raise RuntimeError('register was already called')

    read_fd, write_fd = os.pipe()

    # Python c-level signal handler requires that the write end will be in
    # non blocking mode
    filecontrol.set_non_blocking(write_fd)

    # Set the read pipe end to non-blocking too, just in case.
    filecontrol.set_non_blocking(read_fd)

    # Prevent subproccesses we execute from inheriting the pipes.
    filecontrol.set_close_on_exec(write_fd)
    filecontrol.set_close_on_exec(read_fd)

    signal.set_wakeup_fd(write_fd)

    poller = select.poll()
    poller.register(read_fd, select.POLLIN)

    _signal_poller = poller
    _signal_read_fd = read_fd
Example #9
0
 def _handleSignals(self):
     # Bypass installing the child waker, for now
     _SignalReactorMixin._handleSignals(self)
     try:
         signal.set_wakeup_fd(self._signal_fds.writer_fileno())
     except ValueError:
         pass
Example #10
0
 def _signal_pipe(self):
     # Set up a pipe for SIGCHLD notifications
     wakeup_r, wakeup_w = os.pipe()
     fcntl.fcntl(wakeup_w, fcntl.F_SETFL, # Make the pipe non-blocking
         fcntl.fcntl(wakeup_w, fcntl.F_GETFL, 0) | os.O_NONBLOCK)
     signal.set_wakeup_fd(wakeup_w) # Tell Python to send a byte to this pipe on signal
     signal.signal(signal.SIGCHLD, lambda x,y: None) # Stop ignoring SIGCHLD
     return wakeup_r, wakeup_w
Example #11
0
    def test_invalid_call(self):
        # First parameter is positional-only
        with self.assertRaises(TypeError):
            signal.set_wakeup_fd(signum=signal.SIGINT)

        # warn_on_full_buffer is a keyword-only parameter
        with self.assertRaises(TypeError):
            signal.set_wakeup_fd(signal.SIGINT, False)
    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])
Example #13
0
    def __init__(self):
        self.lock = threading.RLock()
        self.condition = threading.Condition(self.lock)
        # this lock and conditions are used for:
        #
        # - mutual exclusion and synchronization beetween sections of
        # code in _Conductor.__io_loop (conductor thread), and in
        # Process.start() and Process.wait() (main thread)
        #
        # - mutual exclusion beetween sections of code in
        #   _Conductor.__io_loop() (conductor thread) and in
        #   _Conductor.__reaper_thread_func() (reaper thread)

        self.__io_thread = threading.Thread(target = self.__io_thread_func, name = "I/O")
        self.__io_thread.setDaemon(True)
        # thread will terminate automatically when the main thread
        # exits.  once in a while, this can trigger an exception, but
        # this seems to be safe and to be related to this issue:
        # http://bugs.python.org/issue1856
        self.__rpipe, self.__wpipe = os.pipe()  # pipe used to wakeup
                                                # the conductor thread
                                                # from the main thread
                                                # when needed
        _set_fd_nonblocking(self.__rpipe)   # the reading function
                                            # _read_asmuch() relies on
                                            # file descriptors to be non
                                            # blocking
        _set_fd_nonblocking(self.__wpipe)   # because we call
                                            # signal.set_wakeup_fd on this pipe
        self.__poller = poll()   # asynchronous I/O with all
                                 # subprocesses filehandles
        self.__poller.register(self.__rpipe,
                               POLLIN
                               | POLLERR)
        self.__processes = set()    # the set of `Process` handled by
                                    # this `_Conductor`
        self.__fds = dict() # keys: the file descriptors currently polled by
                            # this `_Conductor`
                            #
                            # values: tuples (`Process`, `Process`'s
                            # function to handle activity for this
                            # descriptor)
        self.__pids = dict()    # keys: the pids of the subprocesses
                                # launched by this `_Conductor`
                                #
                                # values: their `Process`
        self.__timeline = [] # heapq of `Process` with a timeout date
        self.__process_actions = queue.Queue()
                                # thread-safe FIFO used to send requests
                                # from main thread and conductor thread:
                                # we enqueue tuples (function to call,
                                # tuple of parameters to pass to this
                                # function))
        self.__reaper_thread_running = False
                                # to keep track wether reaper thread is
                                # running
        signal.set_wakeup_fd(self.__wpipe)
        self.pgrp = self.__start_pgrp()
Example #14
0
    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)
Example #15
0
 def dispose(self, exc=None):
     if self.current[0] == self:
         signal.signal(signal.SIGCHLD, signal.SIG_DFL)
         signal.set_wakeup_fd(-1)
         self.current[0] = None
     error = Result.from_exception(exc or CanceledError('process queue has been disposed'))
     pids, self.pids = self.pids, {}
     for ret in self.pids.values():
         ret(error)
Example #16
0
 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 is_main_thread():
             signal.set_wakeup_fd(self._old_signal_wakeup_fd)
Example #17
0
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()
Example #18
0
 def __init__(self, zkservers, config_path):
   self._signal_notifier = os.pipe()
   signal.set_wakeup_fd(self._signal_notifier[1])
   signal.signal(signal.SIGCHLD, self._sigchld)
   zh = zkwrapper.ZKWrapper(zkservers)
   core.set_default_zkwrapper(zh)
   core.set_default_ping_fd(self._signal_notifier[1])
   self._inotify_watcher = InotifyWatcher([config_path], ConfigFile,
                                          self._is_config_file)
   self._sigchld_received = False
Example #19
0
    def start(self):
        if self._running:
            raise RuntimeError('IOLoop is already running')
        if not logging.getLogger().handlers:
            # The IOLoop catches and logs exceptions, so it's
            # important that log output be visible.  However, python's
            # default behavior for non-root loggers (prior to python
            # 3.2) is to print an unhelpful "no handlers could be
            # found" message rather than the actual log entry, so we
            # must explicitly configure logging if we've made it this
            # far without anything.
            logging.basicConfig()
        if self._stopped:
            self._stopped = False
            return
        old_current = getattr(IOLoop._current, "instance", None)
        IOLoop._current.instance = self
        self._thread_ident = thread.get_ident()

        # pyuv won't interate the loop if the poll is interrupted by
        # a signal, so make sure we can wake it up to catch signals
        # registered with the signal module
        #
        # If someone has already set a wakeup fd, we don't want to
        # disturb it.  This is an issue for twisted, which does its
        # SIGCHILD processing in response to its own wakeup fd being
        # written to.  As long as the wakeup fd is registered on the IOLoop,
        # the loop will still wake up and everything should work.
        old_wakeup_fd = None
        self._signal_checker.stop()
        if hasattr(signal, 'set_wakeup_fd') and os.name == 'posix':
            # requires python 2.6+, unix.  set_wakeup_fd exists but crashes
            # the python process on windows.
            try:
                old_wakeup_fd = signal.set_wakeup_fd(self._fdwaker.writer.fileno())
                if old_wakeup_fd != -1:
                    # Already set, restore previous value.  This is a little racy,
                    # but there's no clean get_wakeup_fd and in real use the
                    # IOLoop is just started once at the beginning.
                    signal.set_wakeup_fd(old_wakeup_fd)
                    old_wakeup_fd = None
                else:
                    self._signal_checker.start()
            except ValueError:  # non-main thread
                pass

        self._running = True
        self._loop.run(pyuv.UV_RUN_DEFAULT)

        # reset the stopped flag so another start/stop pair can be issued
        self._running = False
        self._stopped = False
        IOLoop._current.instance = old_current
        if old_wakeup_fd is not None:
            signal.set_wakeup_fd(old_wakeup_fd)
Example #20
0
    def _set_signal_handlers(self):
        """Set the signal handlers."""
        def noopSignalHandler(*args):
            pass
        self._sigchld_handler = signal.signal(signal.SIGCHLD, noopSignalHandler)
        self._sigint_handler  = signal.signal(signal.SIGINT,  noopSignalHandler)
        self._sigterm_handler = signal.signal(signal.SIGTERM, noopSignalHandler)

        sig_r_fd, sig_w_fd = os.pipe2(os.O_NONBLOCK | os.O_CLOEXEC)
        signal.set_wakeup_fd(sig_w_fd)
        self._add_read_fd_handler(sig_r_fd, self._handle_sig_fd, None)
Example #21
0
def add_signal_watch(signal_action, _sockets=[]):
    """Catches signals which should exit the program and calls `signal_action`
    after the main loop has started, even if the signal occurred before the
    main loop has started.
    """

    # See https://bugzilla.gnome.org/show_bug.cgi?id=622084 for details

    sig_names = ["SIGINT", "SIGTERM", "SIGHUP"]
    if os.name == "nt":
        sig_names = ["SIGINT", "SIGTERM"]

    signals = {}
    for name in sig_names:
        id_ = getattr(signal, name, None)
        if id_ is None:
            continue
        signals[id_] = name

    for signum, name in signals.items():
        # Before the mainloop starts we catch signals in python
        # directly and idle_add the app.quit
        def idle_handler(signum, frame):
            print_d("Python signal handler activated: %s" % signals[signum])
            GLib.idle_add(signal_action, priority=GLib.PRIORITY_HIGH)

        print_d("Register Python signal handler: %r" % name)
        signal.signal(signum, idle_handler)

    read_socket, write_socket = socket.socketpair()
    for sock in [read_socket, write_socket]:
        sock.setblocking(False)
        # prevent it from being GCed and leak it
        _sockets.append(sock)

    def signal_notify(source, condition):
        if condition & GLib.IOCondition.IN:
            try:
                return bool(read_socket.recv(1))
            except EnvironmentError:
                return False
        else:
            return False

    if os.name == "nt":
        channel = GLib.IOChannel.win32_new_socket(read_socket.fileno())
    else:
        channel = GLib.IOChannel.unix_new(read_socket.fileno())
    io_add_watch(channel, GLib.PRIORITY_HIGH,
                 (GLib.IOCondition.IN | GLib.IOCondition.HUP |
                  GLib.IOCondition.NVAL | GLib.IOCondition.ERR),
                 signal_notify)

    signal.set_wakeup_fd(write_socket.fileno())
Example #22
0
    def _shutdown_resources(self):
        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
Example #23
0
 def __init__(self, proactor):
     super().__init__()
     logger.debug('Using proactor: %s', proactor.__class__.__name__)
     self._proactor = proactor
     self._selector = proactor   # convenient alias
     self._self_reading_future = None
     self._accept_futures = {}   # socket file descriptor => Future
     proactor.set_loop(self)
     self._make_self_pipe()
     self_no = self._csock.fileno()
     signal.set_wakeup_fd(self_no)
Example #24
0
    def __init__(self, sockfile, args, executable=None, use_path=True, env=None,
                 restart=False):
        """
        Start a new daemon. The child will be started and Unix socket will be
        opened. Connections are not yet accepted, call the run method to start
        handling connection and hand over the program execution to the
        SignalProxyDaemon.
        :param sockfile: Path to the Unix to listen on
        :param Sequence[str] args: Args of the process to exec
        :param str executable: Optional, if given this executable instead of the
        zeroth argument is used as executable.
        :param bool use_path: Use the PATH variable to find the executable,
        defaults to True
        :param dict[str,str] env: If given set the child process's
        environment, otherwise use the environment of the current process.
        :param bool restart: If True, restart the child process if it died,
        otherwise the SignalProxyDaemon will shut itself down, if the child
        dies.
        """
        if not args:
            raise ValueError("Empty argument list")
        if executable is None:
            executable = args[0]
        self.sockfile = sockfile
        self.restart = restart
        self.args = args
        self.executable = executable
        self.use_path = use_path
        self.env = env
        self.pid = None
        self.last_forkexec = -1

        try:
            options = os.O_CLOEXEC | os.O_NONBLOCK
            self.sig_read_fd, self.sig_write_fd = os.pipe2(options)
            signal.set_wakeup_fd(self.sig_write_fd)
            for signo in self.sigset:
                signal.signal(signo, self._noop_handler)
            logger.info('Listening on %s', sockfile)
            if os.path.exists(sockfile):
                os.unlink(sockfile)
            self.server = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
            self.server.bind(sockfile)
            self.server.setblocking(False)
            self.server.listen(0)
            self.poll = select.poll()
            self.connections = {}
            self._forkexec()
            self.state = DaemonState.started
        except:
            self._restore_signals()
            self._close_files()
            raise
Example #25
0
    def test_set_wakeup_fd_result(self):
        r1, w1 = os.pipe()
        self.addCleanup(os.close, r1)
        self.addCleanup(os.close, w1)
        r2, w2 = os.pipe()
        self.addCleanup(os.close, r2)
        self.addCleanup(os.close, w2)

        signal.set_wakeup_fd(w1)
        self.assertEqual(signal.set_wakeup_fd(w2), w1)
        self.assertEqual(signal.set_wakeup_fd(-1), w2)
        self.assertEqual(signal.set_wakeup_fd(-1), -1)
Example #26
0
File: core.py Project: clones/kaa
    def init(signals, purge=False):
        """
        Initialize the core threading/mainloop functionality by creating the
        thread notifier and signal wakeup pipes, and registering them with
        the notifier.

        :param signals: the main loop Signals object (passed by main.py)
        :param purge: if True, any pending callbacks queued for execution in
                      the mainloop will be removed.  This is useful when we have
                      forked and want to wipe the slate clean.

        This function also installs a SIGCHLD handler, mainly for lack of a
        better place.

        If this function is called multiple times, it must recreate the pipes
        and cleanup after previous invocations.
        """
        log.debug('Creating thread notifier and signal wakeup pipes (purge=%s)', purge)
        if CoreThreading._pipe:
            # There is an existing pipe already, so stop monitoring it.
            notifier.socket_remove(CoreThreading._pipe[0])
        CoreThreading._pipe = CoreThreading._create_nonblocking_pipe()
        notifier.socket_add(CoreThreading._pipe[0], CoreThreading.run_queue)

        if purge:
            with CoreThreading._queue_lock:
                del CoreThreading._queue[:]
        elif CoreThreading._queue:
            # A thread is already running and wanted to run something in the
            # mainloop before the mainloop is started. In that case we need
            # to wakeup the loop ASAP to handle the requests.
            CoreThreading._wakeup()


        # Create wakeup fd pipe (Python 2.6) and install SIGCHLD handler.
        if hasattr(signal, 'set_wakeup_fd'):
            # Python 2.6+, so setup the signal wake pipe.
            if CoreThreading._signal_wake_pipe:
                # Stop monitoring old signal wake pipe.
                notifier.socket_remove(CoreThreading._signal_wake_pipe[0])
            pipe = CoreThreading._create_nonblocking_pipe()
            notifier.socket_add(pipe[0], lambda fd: os.read(fd, 4096) and signals['unix-signal'].emit())
            CoreThreading._signal_wake_pipe = pipe
            signal.signal(signal.SIGCHLD, lambda sig, frame: None)
            signal.set_wakeup_fd(pipe[1])
        else:
            # With Python 2.5-, we can't wakeup the main loop.  Use emit()
            # directly as the handler.
            signal.signal(signal.SIGCHLD, signals['unix-signal'].emit)
        # Emit now to reap processes that may have terminated before we set the
        # handler.  process.py connects to this signal.
        signals['unix-signal'].emit()
    def _trap_sigwatch(self, current, sigset):
        # Initialize the signal handling part of the kernel if not done already
        # Note: This only works if running in the main thread
        if self._signals is None:
            self._signals = defaultdict(list)
            signal.set_wakeup_fd(self._notify_sock.fileno())     
            
        for signo in sigset.signos:
            if not self._signals[signo]:
                self._default_signals[signo] = signal.signal(signo, lambda signo, frame:None)
            self._signals[signo].append(sigset)

        self._reschedule_task(current)
Example #28
0
    def test_set_wakeup_fd_socket_result(self):
        sock1 = socket.socket()
        self.addCleanup(sock1.close)
        fd1 = sock1.fileno()

        sock2 = socket.socket()
        self.addCleanup(sock2.close)
        fd2 = sock2.fileno()

        signal.set_wakeup_fd(fd1)
        self.assertEqual(signal.set_wakeup_fd(fd2), fd1)
        self.assertEqual(signal.set_wakeup_fd(-1), fd2)
        self.assertEqual(signal.set_wakeup_fd(-1), -1)
Example #29
0
	def child_start(self, gc_old_one=False):
		if not self.poller:
			self.poller, (r, w) = select.epoll(), os.pipe()
			signal.set_wakeup_fd(w)
			self.wakeup_fd = os.fdopen(r, 'rb', 0)
			self.poller.register(self.wakeup_fd, select.EPOLLIN)
		if self._child and gc_old_one:
			self._child.wait()
			self._child = None
		if not self.child_cmd or self._child: return
		self._child = subprocess.Popen( self.child_cmd,
			stdout=subprocess.PIPE, stdin=subprocess.PIPE, close_fds=True )
		self._child_readline(init_line=True) # wait until it's ready
Example #30
0
    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