コード例 #1
0
ファイル: process.py プロジェクト: compbrain/madcow
    def reapProcess(self):
        """
        Try to reap a process (without blocking) via waitpid.

        This is called when sigchild is caught or a Process object loses its
        "connection" (stdout is closed) This ought to result in reaping all
        zombie processes, since it will be called twice as often as it needs
        to be.

        (Unfortunately, this is a slightly experimental approach, since
        UNIX has no way to be really sure that your process is going to
        go away w/o blocking.  I don't want to block.)
        """
        try:
            try:
                pid, status = os.waitpid(self.pid, os.WNOHANG)
            except OSError, e:
                if e.errno == errno.ECHILD:
                    # no child process
                    pid = None
                else:
                    raise
        except:
            log.msg('Failed to reap %d:' % self.pid)
            log.err()
            pid = None
        if pid:
            self.processEnded(status)
            unregisterReapProcessHandler(pid, self)
コード例 #2
0
ファイル: tcp.py プロジェクト: compbrain/madcow
 def readConnectionLost(self, reason):
     p = interfaces.IHalfCloseableProtocol(self.protocol, None)
     if p:
         try:
             p.readConnectionLost()
         except:
             log.err()
             self.connectionLost(failure.Failure())
     else:
         self.connectionLost(reason)
コード例 #3
0
ファイル: process.py プロジェクト: compbrain/madcow
 def childConnectionLost(self, childFD, reason):
     # this is called when one of the helpers (ProcessReader or
     # ProcessWriter) notices their pipe has been closed
     os.close(self.pipes[childFD].fileno())
     del self.pipes[childFD]
     try:
         self.proto.childConnectionLost(childFD)
     except:
         log.err()
     self.maybeCallProcessEnded()
コード例 #4
0
ファイル: _baseprocess.py プロジェクト: compbrain/madcow
 def maybeCallProcessEnded(self):
     """
     Call processEnded on protocol after final cleanup.
     """
     if self.proto is not None:
         reason = self._getReason(self.status)
         proto = self.proto
         self.proto = None
         try:
             proto.processEnded(Failure(reason))
         except:
             err(None, "unexpected error in processEnded")
コード例 #5
0
ファイル: defer.py プロジェクト: compbrain/madcow
    def __del__(self):
        """Print tracebacks and die.

        If the *last* (and I do mean *last*) callback leaves me in an error
        state, print a traceback (if said errback is a Failure).
        """
        if self.failResult is not None:
            log.msg("Unhandled error in Deferred:", isError=True)
            debugInfo = self._getDebugTracebacks()
            if debugInfo != '':
                log.msg("(debug: " + debugInfo + ")", isError=True)
            log.err(self.failResult)
コード例 #6
0
ファイル: selectreactor.py プロジェクト: compbrain/madcow
 def _doReadOrWrite(self, selectable, method, dict):
     try:
         why = getattr(selectable, method)()
         handfn = getattr(selectable, 'fileno', None)
         if not handfn:
             why = _NO_FILENO
         elif handfn() == -1:
             why = _NO_FILEDESC
     except:
         why = sys.exc_info()[1]
         log.err()
     if why:
         self._disconnectSelectable(selectable, why, method=="doRead")
コード例 #7
0
ファイル: base.py プロジェクト: compbrain/madcow
 def _continueFiring(self, ignored):
     """
     Call the during and after phase triggers for this event.
     """
     self.state = 'BASE'
     self.finishedBefore = []
     for phase in self.during, self.after:
         while phase:
             callable, args, kwargs = phase.pop(0)
             try:
                 callable(*args, **kwargs)
             except:
                 log.err()
コード例 #8
0
ファイル: tcp.py プロジェクト: compbrain/madcow
 def _closeWriteConnection(self):
     try:
         getattr(self.socket, self._socketShutdownMethod)(1)
     except socket.error:
         pass
     p = interfaces.IHalfCloseableProtocol(self.protocol, None)
     if p:
         try:
             p.writeConnectionLost()
         except:
             f = failure.Failure()
             log.err()
             self.connectionLost(f)
コード例 #9
0
ファイル: process.py プロジェクト: compbrain/madcow
    def __init__(self, reactor, executable, args, environment, path, proto,
                 uid=None, gid=None, usePTY=None):
        """
        Spawn an operating-system process.

        This is where the hard work of disconnecting all currently open
        files / forking / executing the new process happens.  (This is
        executed automatically when a Process is instantiated.)

        This will also run the subprocess as a given user ID and group ID, if
        specified.  (Implementation Note: this doesn't support all the arcane
        nuances of setXXuid on UNIX: it will assume that either your effective
        or real UID is 0.)
        """
        if pty is None and not isinstance(usePTY, (tuple, list)):
            # no pty module and we didn't get a pty to use
            raise NotImplementedError(
                "cannot use PTYProcess on platforms without the pty module.")
        abstract.FileDescriptor.__init__(self, reactor)
        _BaseProcess.__init__(self, proto)

        if isinstance(usePTY, (tuple, list)):
            masterfd, slavefd, ttyname = usePTY
        else:
            masterfd, slavefd = pty.openpty()
            ttyname = os.ttyname(slavefd)

        try:
            self._fork(path, uid, gid, executable, args, environment,
                       masterfd=masterfd, slavefd=slavefd)
        except:
            if not isinstance(usePTY, (tuple, list)):
                os.close(masterfd)
                os.close(slavefd)
            raise

        # we are now in parent process:
        os.close(slavefd)
        fdesc.setNonBlocking(masterfd)
        self.fd = masterfd
        self.startReading()
        self.connected = 1
        self.status = -1
        try:
            self.proto.makeConnection(self)
        except:
            log.err()
        registerReapProcessHandler(self.pid, self)
コード例 #10
0
ファイル: base.py プロジェクト: compbrain/madcow
 def fireEvent(self):
     """
     Call the triggers added to this event.
     """
     self.state = 'BEFORE'
     self.finishedBefore = []
     beforeResults = []
     while self.before:
         callable, args, kwargs = self.before.pop(0)
         self.finishedBefore.append((callable, args, kwargs))
         try:
             result = callable(*args, **kwargs)
         except:
             log.err()
         else:
             if isinstance(result, Deferred):
                 beforeResults.append(result)
     DeferredList(beforeResults).addCallback(self._continueFiring)
コード例 #11
0
ファイル: base.py プロジェクト: compbrain/madcow
    def mainLoop(self):
        while self._started:
            try:
                while self._started:
                    # Advance simulation time in delayed event
                    # processors.
                    self.runUntilCurrent()

                    # XXX f**k this shit.. WHY does twisted's select()
                    # block signals? this is NOT NORMAL
                    self.doIteration(1)

                    #t2 = self.timeout()
                    #t = self.running and t2
                    #self.doIteration(t)
            except:
                log.msg("Unexpected error in main loop.")
                log.err()
            else:
                log.msg('Main loop terminated.')
コード例 #12
0
ファイル: process.py プロジェクト: compbrain/madcow
def registerReapProcessHandler(pid, process):
    """
    Register a process handler for the given pid, in case L{reapAllProcesses}
    is called.

    @param pid: the pid of the process.
    @param process: a process handler.
    """
    if pid in reapProcessHandlers:
        raise RuntimeError("Try to register an already registered process.")
    try:
        auxPID, status = os.waitpid(pid, os.WNOHANG)
    except:
        log.msg('Failed to reap %d:' % pid)
        log.err()
        auxPID = None
    if auxPID:
        process.processEnded(status)
    else:
        # if auxPID is 0, there are children but none have exited
        reapProcessHandlers[pid] = process
コード例 #13
0
ファイル: udp.py プロジェクト: compbrain/madcow
 def doRead(self):
     """Called when my socket is ready for reading."""
     read = 0
     while read < self.maxThroughput:
         try:
             data, addr = self.socket.recvfrom(self.maxPacketSize)
         except socket.error, se:
             no = se.args[0]
             if no in (EAGAIN, EINTR, EWOULDBLOCK):
                 return
             if (no == ECONNREFUSED) or (platformType == "win32" and no == WSAECONNRESET):
                 if self._connectedAddr:
                     self.protocol.connectionRefused()
             else:
                 raise
         else:
             read += len(data)
             try:
                 self.protocol.datagramReceived(data, addr)
             except:
                 log.err()
コード例 #14
0
ファイル: selectreactor.py プロジェクト: compbrain/madcow
    def doSelect(self, timeout):
        """
        Run one iteration of the I/O monitor loop.

        This will run all selectables who had input or output readiness
        waiting for them.
        """
        while 1:
            try:
                r, w, ignored = _select(self._reads.keys(),
                                        self._writes.keys(),
                                        [], timeout)
                break
            except ValueError, ve:
                # Possibly a file descriptor has gone negative?
                log.err()
                self._preenDescriptors()
            except TypeError, te:
                # Something *totally* invalid (object w/o fileno, non-integral
                # result) was passed
                log.err()
                self._preenDescriptors()
コード例 #15
0
ファイル: tcp.py プロジェクト: compbrain/madcow
 def doRead(self):
     if self.disconnected:
         # See the comment in the similar check in doWrite below.
         # Additionally, in order for anything other than returning
         # CONNECTION_DONE here to make sense, it will probably be necessary
         # to implement a way to switch back to TCP from TLS (actually, if
         # we did something other than return CONNECTION_DONE, that would be
         # a big part of implementing that feature).  In other words, the
         # expectation is that doRead will be called when self.disconnected
         # is True only when the connection has been lost.  It's possible
         # that the other end could stop speaking TLS and then send us some
         # non-TLS data.  We'll end up ignoring that data and dropping the
         # connection.  There's no unit tests for this check in the cases
         # where it makes a difference.  The test suite only hits this
         # codepath when it would have otherwise hit the SSL.ZeroReturnError
         # exception handler below, which has exactly the same behavior as
         # this conditional.  Maybe that's the only case that can ever be
         # triggered, I'm not sure.  -exarkun
         return main.CONNECTION_DONE
     if self.writeBlockedOnRead:
         self.writeBlockedOnRead = 0
         self._resetReadWrite()
     try:
         return Connection.doRead(self)
     except SSL.ZeroReturnError:
         return main.CONNECTION_DONE
     except SSL.WantReadError:
         return
     except SSL.WantWriteError:
         self.readBlockedOnWrite = 1
         Connection.startWriting(self)
         Connection.stopReading(self)
         return
     except SSL.SysCallError, (retval, desc):
         if ((retval == -1 and desc == 'Unexpected EOF')
             or retval > 0):
             return main.CONNECTION_LOST
         log.err()
         return main.CONNECTION_LOST
コード例 #16
0
ファイル: base.py プロジェクト: compbrain/madcow
    def runUntilCurrent(self):
        """Run all pending timed calls.
        """
        if self.threadCallQueue:
            # Keep track of how many calls we actually make, as we're
            # making them, in case another call is added to the queue
            # while we're in this loop.
            count = 0
            total = len(self.threadCallQueue)
            for (f, a, kw) in self.threadCallQueue:
                try:
                    f(*a, **kw)
                except:
                    log.err()
                count += 1
                if count == total:
                    break
            del self.threadCallQueue[:count]
            if self.threadCallQueue:
                self.wakeUp()

        # insert new delayed calls now
        self._insertNewDelayedCalls()

        now = self.seconds()
        while self._pendingTimedCalls and (self._pendingTimedCalls[0].time <= now):
            call = heappop(self._pendingTimedCalls)
            if call.cancelled:
                self._cancellations-=1
                continue

            if call.delayed_time > 0:
                call.activate_delay()
                heappush(self._pendingTimedCalls, call)
                continue

            try:
                call.called = 1
                call.func(*call.args, **call.kw)
            except:
                log.deferr()
                if hasattr(call, "creator"):
                    e = "\n"
                    e += " C: previous exception occurred in " + \
                         "a DelayedCall created here:\n"
                    e += " C:"
                    e += "".join(call.creator).rstrip().replace("\n","\n C:")
                    e += "\n"
                    log.msg(e)


        if (self._cancellations > 50 and
             self._cancellations > len(self._pendingTimedCalls) >> 1):
            self._cancellations = 0
            self._pendingTimedCalls = [x for x in self._pendingTimedCalls
                                       if not x.cancelled]
            heapify(self._pendingTimedCalls)

        if self._justStopped:
            self._justStopped = False
            self.fireSystemEvent("shutdown")
コード例 #17
0
ファイル: process.py プロジェクト: compbrain/madcow
    def __init__(self,
                 reactor, executable, args, environment, path, proto,
                 uid=None, gid=None, childFDs=None):
        """
        Spawn an operating-system process.

        This is where the hard work of disconnecting all currently open
        files / forking / executing the new process happens.  (This is
        executed automatically when a Process is instantiated.)

        This will also run the subprocess as a given user ID and group ID, if
        specified.  (Implementation Note: this doesn't support all the arcane
        nuances of setXXuid on UNIX: it will assume that either your effective
        or real UID is 0.)
        """
        if not proto:
            assert 'r' not in childFDs.values()
            assert 'w' not in childFDs.values()
        _BaseProcess.__init__(self, proto)

        self.pipes = {}
        # keys are childFDs, we can sense them closing
        # values are ProcessReader/ProcessWriters

        helpers = {}
        # keys are childFDs
        # values are parentFDs

        if childFDs is None:
            childFDs = {0: "w", # we write to the child's stdin
                        1: "r", # we read from their stdout
                        2: "r", # and we read from their stderr
                        }

        debug = self.debug
        if debug: print "childFDs", childFDs

        _openedPipes = []
        def pipe():
            r, w = os.pipe()
            _openedPipes.extend([r, w])
            return r, w

        # fdmap.keys() are filenos of pipes that are used by the child.
        fdmap = {} # maps childFD to parentFD
        try:
            for childFD, target in childFDs.items():
                if debug: print "[%d]" % childFD, target
                if target == "r":
                    # we need a pipe that the parent can read from
                    readFD, writeFD = pipe()
                    if debug: print "readFD=%d, writeFD=%d" % (readFD, writeFD)
                    fdmap[childFD] = writeFD     # child writes to this
                    helpers[childFD] = readFD    # parent reads from this
                elif target == "w":
                    # we need a pipe that the parent can write to
                    readFD, writeFD = pipe()
                    if debug: print "readFD=%d, writeFD=%d" % (readFD, writeFD)
                    fdmap[childFD] = readFD      # child reads from this
                    helpers[childFD] = writeFD   # parent writes to this
                else:
                    assert type(target) == int, '%r should be an int' % (target,)
                    fdmap[childFD] = target      # parent ignores this
            if debug: print "fdmap", fdmap
            if debug: print "helpers", helpers
            # the child only cares about fdmap.values()

            self._fork(path, uid, gid, executable, args, environment, fdmap=fdmap)
        except:
            map(os.close, _openedPipes)
            raise

        # we are the parent process:
        self.proto = proto

        # arrange for the parent-side pipes to be read and written
        for childFD, parentFD in helpers.items():
            os.close(fdmap[childFD])

            if childFDs[childFD] == "r":
                reader = self.processReaderFactory(reactor, self, childFD,
                                        parentFD)
                self.pipes[childFD] = reader

            if childFDs[childFD] == "w":
                writer = self.processWriterFactory(reactor, self, childFD,
                                        parentFD, forceReadHack=True)
                self.pipes[childFD] = writer

        try:
            # the 'transport' is used for some compatibility methods
            if self.proto is not None:
                self.proto.makeConnection(self)
        except:
            log.err()
        registerReapProcessHandler(self.pid, self)
コード例 #18
0
ファイル: defer.py プロジェクト: compbrain/madcow
def logError(err):
    log.err(err)
    return err