Esempio n. 1
0
def loop(condition, timeout=None):
    """
    Executes the main loop until condition is met.

    This function may be called recursively, however two loops may not
    run in parallel threads.

    :param condition: a callable or object that is evaluated after each step
                      of the loop.  If it evaluates False, the loop
                      terminates.  (If condition is therefore ``True``, the
                      loop will run forever.)
    :param timeout: number of seconds after which the loop will terminate
                    (regardless of the condition).
    """
    _loop_lock.acquire()
    if is_running() and not is_mainthread():
        # race condition. Two threads started a mainloop and the other
        # one is executed right now. Raise a RuntimeError
        _loop_lock.release()
        raise RuntimeError('loop running in a different thread')

    initial_mainloop = False
    if not is_running():
        # no mainloop is running, set this thread as mainloop and
        # set the internal running state.
        initial_mainloop = True
        set_as_mainthread()
        _set_running(True)
    # ok, that was the critical part
    _loop_lock.release()

    if not callable(condition):
        condition = lambda: condition

    abort = []
    if timeout is not None:
        # timeout handling to stop the mainloop after the given timeout
        # even when the condition is still True.
        sec = timeout
        timeout = OneShotTimer(lambda: abort.append(True))
        timeout.start(sec)

    try:
        while condition() and not abort:
            try:
                notifier.step()
                signals['step'].emit()
            except BaseException, e:
                if signals['exception'].emit(*sys.exc_info()) != False:
                    # Either there are no global exception handlers, or none of
                    # them explicitly returned False to abort mainloop
                    # termination.  So abort the main loop.
                    type, value, tb = sys.exc_info()
                    raise type, value, tb
    finally:
        # make sure we set mainloop status
        if timeout is not None:
            timeout.stop()
        if initial_mainloop:
            _set_running(False)
Esempio n. 2
0
File: popen.py Progetto: clones/kaa
    def stop( self, cmd = None ):
        """
        Stop the child. If 'cmd' is given, this stop command will send to
        the app to stop itself. If this is not working, kill -15 and kill -9
        will be used to kill the app.

        Returns an InProgress which finishes when the process stops.
        """
        if self.stopping:
            return inprogress(self.signals['completed'])

        if not is_mainthread():
            return MainThreadCallback(self.stop, cmd)()

        self.stopping = True
        cmd = cmd or self._stop_cmd

        if self.is_alive() and not self.__kill_timer:
            if cmd:
                log.info('sending exit command to app')
                if callable(cmd):
                    cmd()
                else:
                    self.write(cmd)

                cb = Callback( self.__kill, 15 )
                self.__kill_timer = notifier.timer_add( 3000, cb )
            else:
                cb = Callback( self.__kill, 15 )
                self.__kill_timer = notifier.timer_add( 0, cb )

        return inprogress(self.signals['completed'])
Esempio n. 3
0
 def unregister(self):
     """
     Unregister the IOMonitor
     """
     if not self.active:
         return
     if not is_mainthread():
         return MainThreadCallback(self.unregister)()
     notifier.socket_remove(self._id, self._condition-1)
     super(IOMonitor, self).unregister()
Esempio n. 4
0
 def post(self, *args):
     """
     Post event into the queue.
     """
     event = self
     if args:
         event = copy.copy(self)
         event._set_args(args)
     if not is_mainthread():
         return MainThreadCallback(manager.post, event)()
     else:
         return manager.post(event)
Esempio n. 5
0
def _shutdown_check(*args):
    # Helper function to shutdown kaa on system exit
    # The problem is that pytgtk just exits python and
    # does not simply return from the main loop and kaa
    # can't call the shutdown handler. This is not a perfect
    # solution, e.g. with the generic mainloop you can do
    # stuff after kaa.main.run() which is not possible with gtk
    if is_running():
        # If the kaa mainthread (i.e. thread the mainloop is running in)
        # is not the program's main thread, then is_mainthread() will be False
        # and we don't need to set running=False since shutdown() will raise a
        # SystemExit and things will exit normally.
        if is_mainthread():
            _set_running(False)
        stop()
Esempio n. 6
0
def step(*args, **kwargs):
    """
    Performs a single iteration of the main loop.

    This function should almost certainly never be called directly.  Use it
    at your own peril.
    """
    if not is_mainthread():
        # If step is being called from a thread, wake up the mainthread
        # instead of allowing the thread into notifier.step.
        wakeup()
        # Sleep for epsilon to prevent busy loops.
        time.sleep(0.001)
        return
    notifier.step(*args, **kwargs)
    signals['step'].emit()
Esempio n. 7
0
    def wait(self, timeout=None):
        """
        Blocks until the InProgress is finished.
        
        The main loop is kept alive if waiting in the main thread, otherwise
        the thread is blocked until another thread finishes the InProgress.

        If the InProgress finishes due to an exception, that exception is
        raised.

        :param timeout: if not None, wait() blocks for at most timeout seconds
                        (which may be fractional).  If wait times out, a
                        TimeoutException is raised.
        :return: the value the InProgress finished with
        """
        # Connect a dummy handler to ourselves.  This is a bit kludgy, but
        # solves a particular problem with InProgress(Any|All), which don't
        # actually finish unless something wants to know.  Normally, without
        # wait, we are yielded to the coroutine wrapper which implicitly
        # connects to us.  Here, with wait(), in a sense we want to know when
        # self finishes.
        dummy = lambda *args, **kwargs: None
        self.connect(dummy)

        if is_mainthread():
            # We're waiting in the main thread, so we must keep the mainloop
            # alive by calling main.loop() until we're finished.
            main.loop(lambda: not self.finished, timeout)
        elif not main.is_running():
            # Seems that no loop is running, try to loop
            try:
                main.loop(lambda: not self.finished, timeout)
            except RuntimeError:
                # oops, there is something running, wait
                self._finished_event.wait(timeout)
        else:
            # We're waiting in some other thread, so wait for some other
            # thread to wake us up.
            self._finished_event.wait(timeout)

        if not self.finished:
            self.disconnect(dummy)
            raise TimeoutException

        return self.result
Esempio n. 8
0
File: popen.py Progetto: clones/kaa
    def start(self, args = None):
        """
        Starts the process.  If args is not None, it can be either a list or
        string, as with the constructor, and is appended to the command line
        specified in the constructor.
        """
        if not self.__dead:
            raise SystemError, "Process is already running."
        if self.stopping:
            raise SystemError, "Process isn't done stopping yet."

        cmd = self._cmd + self._normalize_cmd(args)
        self.__kill_timer = None
        self.__dead = False
        self.binary = cmd[0]

        self.child = popen2.Popen3( cmd, True, 100 )

        flags = fcntl.fcntl(self.child.tochild.fileno(), fcntl.F_GETFL)
        fcntl.fcntl( self.child.tochild.fileno(), fcntl.F_SETFL, flags | os.O_NONBLOCK )
        self._wmon = IOMonitor(self._handle_write)
        if self._write_buffer:
            self._wmon.register(self.child.tochild, IO_WRITE)

        log.info('running %s (pid=%s)' % ( self.binary, self.child.pid ) )

        # IO_Handler for stdout
        self.stdout = IO_Handler( 'stdout', self.child.fromchild,
                                  self.signals["stdout"], self.signals['raw-stdout'], self._debugname )
        # IO_Handler for stderr
        self.stderr = IO_Handler( 'stderr', self.child.childerr,
                                  self.signals["stderr"], self.signals['raw-stderr'], self._debugname )

        # add child to watcher
        if not is_mainthread():
            MainThreadCallback(proclist.append)(self, self.__child_died)
        else:
            proclist.append( self, self.__child_died )
        self.in_progress = InProgress()
        return self.in_progress
Esempio n. 9
0
    def register(self, fd, condition = IO_READ):
        """
        Register the IOMonitor to a specific file descriptor.

        The IOMonitor is registered with the notifier, which means that the
        notifier holds a reference to the IOMonitor until it is explicitly
        unregistered (or until the file descriptor is closed).

        :param fd: The file descriptor to monitor.
        :type fd: File descriptor or any file-like object
        :param condition: IO_READ or IO_WRITE
        """
        if self.active:
            if fd != self._id or condition != self._condition:
                raise ValueError('Existing file descriptor already registered with this IOMonitor.')
            return
        if not is_mainthread():
            return MainThreadCallback(self.register)(fd, condition)
        notifier.socket_add(fd, self, condition-1)
        self._condition = condition
        # Must be called _id to correspond with base class.
        self._id = fd