Example #1
0
 def test__propagates_errors_from_command(self):
     do_nothing = lambda obj: None
     proto = JSONPerLineProtocol(callback=do_nothing)
     proto.connectionMade()
     reason = Failure(ProcessTerminated(1))
     proto.processEnded(reason)
     with ExpectedException(ProcessTerminated):
         yield proto.done
Example #2
0
 def loseConnection(self):
     if self.closed: return
     self.closed = 1
     self.proto.inConnectionLost()
     self.proto.outConnectionLost()
     self.proto.errConnectionLost()
     self.proto.processEnded(
         failure.Failure(ProcessTerminated(0, None, None)))
Example #3
0
    def request_exit_status(self, data):
        stat = struct.unpack('>L', data)[0]
        if stat:
            res = ProcessTerminated(exitCode=stat)
        else:
            res = ProcessDone(stat)

        self._protocol.commandExited(Failure(res))
Example #4
0
 def test_error_exit(self):
     """If the subprocess exits with exit code 1, the ``Deferred`` returned
     from ``zfs_command`` errbacks with ``CommandFailed``.
     """
     reactor = FakeProcessReactor()
     result = zfs_command(reactor, [b"-H", b"lalala"])
     process_protocol = reactor.processes[0].processProtocol
     process_protocol.processEnded(Failure(ProcessTerminated(1)))
     self.failureResultOf(result, CommandFailed)
Example #5
0
 def test_bad_arguments_exit(self):
     """If the subprocess exits with exit code 2, the ``Deferred`` returned
     from ``zfs_command`` errbacks with ``BadArguments``.
     """
     reactor = FakeProcessReactor()
     result = zfs_command(reactor, [b"-H", b"lalala"])
     process_protocol = reactor.processes[0].processProtocol
     process_protocol.processEnded(Failure(ProcessTerminated(2)))
     self.failureResultOf(result, BadArguments)
Example #6
0
 def closed(self):
     if self._exitCode or self._signal:
         reason = failure.Failure(
             ProcessTerminated(self._exitCode, self._signal, self.status))
     else:
         reason = failure.Failure(ProcessDone(status=self.status))
     processProtocol = self.processProtocol
     del self.processProtocol
     processProtocol.processEnded(reason)
Example #7
0
    def request_exit_signal(self, data):
        """
        When the server sends the shell's exit status, record it for later
        delivery to the protocol.

        @param data: The network-order four byte representation of the exit
            signal of the shell.
        @type data: L{bytes}
        """
        (signal, ) = unpack('>L', data)
        self._reason = ProcessTerminated(None, signal, None)
Example #8
0
 def loseConnection(self):
     """
     Disconnect the protocol associated with this transport.
     """
     if self.closed:
         return
     self.closed = 1
     self.proto.inConnectionLost()
     self.proto.outConnectionLost()
     self.proto.errConnectionLost()
     self.proto.processEnded(failure.Failure(ProcessTerminated(255, None, None)))
Example #9
0
    def test_process_dies_shortly_after_fork(self):
        """
        If the service process exists right after having been spawned (for
        example the executable was not found), the 'ready' Deferred fires
        with an errback.
        """
        self.protocol.makeConnection(self.process)

        error = ProcessTerminated(exitCode=1, signal=None)
        self.protocol.processExited(Failure(error))
        self.assertThat(self.protocol.ready,
                        failed(MatchesStructure(value=Is(error))))
Example #10
0
def sync_spawn_process(process_protocol,
                       argv=(),
                       reactor_process=None,
                       timeout=None):
    """Execute and capture a process'es standard output."""
    if reactor_process is None:  # noqa: no-cover
        from twisted.internet import reactor  # noqa: no-cover
        reactor_process = reactor  # noqa: no-cover

    import threading

    event = threading.Event()
    output = [None, None]

    def _cb(result):
        if hasattr(result, 'decode'):  # noqa: no-cover
            result = result.decode('utf-8')

        output[0] = result.rstrip("\r\n")
        event.set()

    def _cbe(result):
        output[0] = result
        event.set()

    def _main(args):
        d, output[1] = async_spawn_process(process_protocol, args,
                                           reactor_process)
        d.addCallback(_cb)
        d.addErrback(_cbe)

    reactor_process.callFromThread(_main, argv)

    if event.wait(timeout) is not True:
        if output[1] is not None:
            # We timed-out; kill that program!
            try:
                output[1].signalProcess('TERM')
                output[1].signalProcess('KILL')
            except ProcessExitedAlready:  # noqa: no-cover
                pass  # noqa: no-cover
            output[1].loseConnection()

            # Now raise an exception with the standard exit code for timeout. See timeout(1).
            raise ProcessTerminated(exitCode=124)
        else:  # noqa: no-cover
            LOGGER.error(
                "A time-out occurred without a process handle present.")

    if isinstance(output[0], Failure):
        output[0].raiseException()

    return output[0]
Example #11
0
    def test_unregisters_killer_failure(self):
        """
        When the process fails, the before-shutdown event is unregistered.
        """
        reactor = ProcessCoreReactor()
        d = run(reactor, ['command', 'and', 'args'])
        [process] = reactor.processes

        process.processProtocol.processEnded(Failure(ProcessTerminated(1)))
        self.failureResultOf(d)

        self.assertEqual(reactor._triggers['shutdown'].before, [])
Example #12
0
    def request_exit_status(self, data):
        """
        When the server sends the command's exit status, record it for later
        delivery to the protocol.

        @param data: The network-order four byte representation of the exit
            status of the command.
        @type data: L{bytes}
        """
        (status, ) = unpack(">L", data)
        if status != 0:
            self._reason = ProcessTerminated(status, None, None)
Example #13
0
 def test_other_exit(self):
     """
     If the subprocess exits with exit code other than 0, 1 or 2, the
     ``Deferred`` returned from ``zfs_command`` errbacks with
     whatever error the process exited with.
     """
     reactor = FakeProcessReactor()
     result = zfs_command(reactor, [b"-H", b"lalala"])
     process_protocol = reactor.processes[0].processProtocol
     exception = ProcessTerminated(99)
     process_protocol.processEnded(Failure(exception))
     self.assertEqual(self.failureResultOf(result).value, exception)
Example #14
0
    def test_process_failure(self):
        """
        If the process ends with a failure, the returned deferred fires with
        the reason.
        """

        reactor = ProcessCoreReactor()
        d = run(reactor, ['command', 'and', 'args'])
        [process] = reactor.processes

        expected_failure = Failure(ProcessTerminated(1))
        process.processProtocol.processEnded(expected_failure)
        self.assertEqual(self.failureResultOf(d), expected_failure)
Example #15
0
 def test_processEndedWithExitSignalNoCoreDump(self):
     """
     When processEnded is called, if there is an exit signal in the
     reason it should be sent in an exit-signal message.  If no
     core was dumped, don't set the core-dump bit.
     """
     self.pp.processEnded(Failure(ProcessTerminated(1, signal.SIGTERM, 0)))
     # see comments in test_processEndedWithExitSignalCoreDump for the
     # meaning of the parts in the request
     self.assertRequestsEqual([
         ('exit-signal', NS('TERM') + '\x00' + NS('') + NS(''), False)
     ])
     self.assertSessionClosed()
Example #16
0
def async_spawn_process(process_protocol, args, reactor_process=None):
    """Execute a process using ```Twisted```."""
    if reactor_process is None:  # noqa: no-cover
        from twisted.internet import reactor  # noqa: no-cover
        reactor_process = reactor  # noqa: no-cover

    try:
        process = reactor_process.spawnProcess(process_protocol,
                                               args[0],
                                               args,
                                               env=None)
        return process_protocol.d, process
    except OSError as e:  # noqa: no-cover
        if e.errno is None or e.errno == errno.ENOENT:
            return defer.fail(ProcessTerminated(exitCode=1)), None
        else:
            return defer.fail(e), None
Example #17
0
 def test_processEndedWithExitSignalCoreDump(self):
     """
     When processEnded is called, if there is an exit signal in the reason
     it should be sent in an exit-signal message.  The connection should be
     closed.
     """
     self.pp.processEnded(
         Failure(ProcessTerminated(1, signal.SIGTERM,
                                   1 << 7)))  # 7th bit means core dumped
     self.assertRequestsEqual([(
         'exit-signal',
         common.NS('TERM')  # signal name
         + '\x01'  # core dumped is true
         + common.NS('')  # error message
         + common.NS(''),  # language tag
         False)])
     self.assertSessionClosed()
Example #18
0
    def test_process_dies_while_probing_port(self):
        """
        If the service process exists while waiting for the expected port to,
        be open, the 'ready' Deferred fires with an errback.
        """
        self.protocol.expectedPort = 1234
        self.protocol.makeConnection(self.process)

        self.reactor.advance(self.protocol.minUptime)

        error = ProcessTerminated(exitCode=1, signal=None)
        self.protocol.processExited(Failure(error))
        self.assertThat(self.protocol.ready,
                        failed(MatchesStructure(value=Is(error))))

        # No further probe will happen
        self.reactor.advance(0.1)
        self.assertEqual(1, len(self.reactor.tcpClients))
Example #19
0
    def test_process_dies_while_waiting_expected_output(self):
        """
        If the service process exists while waiting for the expected output,
        the 'ready' Deferred fires with an errback.
        """
        self.protocol.expectedOutput = "hello"
        self.protocol.makeConnection(self.process)

        self.reactor.advance(self.protocol.minUptime)

        error = ProcessTerminated(exitCode=1, signal=None)
        self.protocol.processExited(Failure(error))
        self.assertThat(self.protocol.ready,
                        failed(MatchesStructure(value=Is(error))))

        # Further input received on the file descriptor will be discarded
        self.protocol.ready = Deferred()  # pretend that we didn't get fired
        self.protocol.outReceived(b"hello world!\n")
        self.assertThat(self.protocol.ready, has_no_result())
Example #20
0
    def test_process_ends_after_timeout(self):
        """
        If the process ends after the error checking timeout has passed
        C{result} will not be re-fired.
        """
        message = {"type": "shutdown", "reboot": False, "operation-id": 100}
        self.plugin.perform_shutdown(message)

        stash = []

        def restart_performed(ignore):
            self.assertEqual(stash, [])
            stash.append(True)

        [arguments] = self.process_factory.spawns
        protocol = arguments[0]
        protocol.result.addCallback(restart_performed)
        self.manager.reactor.advance(10)
        protocol.processEnded(Failure(ProcessTerminated(exitCode=1)))
        return protocol.result
Example #21
0
    def __init__(self, proto, code, message):
        proto.makeConnection(self)
        proto.childDataReceived(2, message + '\n')

        proto.childConnectionLost(0)
        proto.childConnectionLost(1)
        proto.childConnectionLost(2)

        failure = Failure(ProcessTerminated(code))

        proto.processExited(failure)
        proto.processEnded(failure)

        # ignore all unused methods
        noop = lambda *args, **kwargs: None
        self.closeStdin = noop
        self.closeStdout = noop
        self.closeStderr = noop
        self.writeToChild = noop
        self.loseConnection = noop
        self.signalProcess = noop
Example #22
0
 def return_path_error():
     proto.errReceived('\n ! Invalid path.')
     proto.errReceived('\n ! Syntax is: [email protected]:<app>.git where '
                       '<app> is your app\'s name.\n\n')
     reason = failure.Failure(ProcessTerminated(exitCode=1))
     return proto.processEnded(reason)
Example #23
0
 def cbErrResponse(err):
     proto.errReceived('\n ! Unable to contact build server.\n\n')
     reason = failure.Failure(ProcessTerminated(exitCode=127))
     return proto.processEnded(reason)
Example #24
0
 def _getReason(self, status):
     exitCode, signal = status
     if exitCode or signal:
         return ProcessTerminated(exitCode, signal, status)
     return ProcessDone(status)
Example #25
0
 def __init__(self, p):
     p.makeConnection(self)
     p.processEnded(failure.Failure(ProcessTerminated(255, None, None)))
Example #26
0
 def request_exit_signal(self, data):
     signame, rest = getNS(data)
     core_dumped = struct.unpack('>?', rest[0])[0]
     msg, lang, rest = getNS(rest[1:], 2)
     self._protocol.commandExited(
         Failure(ProcessTerminated(signal=signame, status=msg)))
Example #27
0
 def _getReason(self, status):
     status = signal = None
     if self.signalled:
         signal = status
     return Failure(ProcessTerminated(status=status, signal=signal))
Example #28
0
 def connectionMade(self):
     data = slurpTextfile(services_file).replace('\n', '\r\n')
     self.transport.write(data)
     self.transport.processEnded(Failure(ProcessTerminated(0, None, None)))
     self.transport.loseConnection()