diff --git a/docs/howitworks.rst b/docs/howitworks.rst index 0b0ae42d..b14ceab7 100644 --- a/docs/howitworks.rst +++ b/docs/howitworks.rst @@ -51,7 +51,7 @@ can be recovered by the bootstrapped process later. It then forks into a new process. After fork, the parent half overwrites its ``stdin`` with the read end of the -pipe, and the child half writes the string ``EC0\n``, then begins reading the +pipe, and the child half writes the string ``MITOGEN0\n``, then begins reading the :py:mod:`zlib`-compressed payload supplied on ``stdin`` by the master, and writing the decompressed result to the write-end of the UNIX pipe. @@ -112,12 +112,17 @@ fetched from the master a second time. Signalling Success ################## -Once the first stage has signalled ``EC0\n``, the master knows it is ready to -receive the compressed bootstrap. After decompressing and writing the bootstrap -source to its parent Python interpreter, the first stage writes the string -``EC1\n`` to ``stdout`` before exiting. The master process waits for this -string before considering bootstrap successful and the child's ``stdio`` ready -to receive messages. +Once the first stage has signalled ``MITO000\n``, the master knows it is ready +to receive the compressed bootstrap. After decompressing and writing the +bootstrap source to its parent Python interpreter, the first stage writes the +string ``MITO001\n`` to ``stdout`` before exiting. The master process waits for +this string before considering bootstrap successful and the child's ``stdio`` +ready to receive messages. + +The signal value is 8 bytes to match the minimum chunk size required to +disambiguate between lines containing an interesting token during SSH password +authentication, a debug message from the SSH client itself, or a message from +the first stage. ExternalContext.main() diff --git a/mitogen/parent.py b/mitogen/parent.py index 4e2b1c60..c999c89a 100644 --- a/mitogen/parent.py +++ b/mitogen/parent.py @@ -790,11 +790,11 @@ class Stream(mitogen.core.Stream): sys.executable += sys.version[:3] os.environ['ARGV0']=sys.executable os.execl(sys.executable,sys.executable+'(mitogen:CONTEXT_NAME)') - os.write(1,'EC0\n') + os.write(1,'MITO000\n') C=_(os.fdopen(0,'rb').read(PREAMBLE_COMPRESSED_LEN),'zip') os.fdopen(W,'w',0).write(C) os.fdopen(w,'w',0).write('PREAMBLE_LEN\n'+C) - os.write(1,'EC1\n') + os.write(1,'MITO001\n') def get_boot_command(self): source = inspect.getsource(self._first_stage) @@ -870,13 +870,17 @@ class Stream(mitogen.core.Stream): self._reap_child() raise + #: For ssh.py, this must be at least max(len('password'), len('debug1:')) + EC0_MARKER = 'MITO000\n' + EC1_MARKER = 'MITO001\n' + def _ec0_received(self): LOG.debug('%r._ec0_received()', self) write_all(self.transmit_side.fd, self.get_preamble()) - discard_until(self.receive_side.fd, 'EC1\n', self.connect_deadline) + discard_until(self.receive_side.fd, 'MITO001\n', self.connect_deadline) def _connect_bootstrap(self, extra_fd): - discard_until(self.receive_side.fd, 'EC0\n', self.connect_deadline) + discard_until(self.receive_side.fd, 'MITO000\n', self.connect_deadline) self._ec0_received() diff --git a/mitogen/ssh.py b/mitogen/ssh.py index c710f990..161b5323 100644 --- a/mitogen/ssh.py +++ b/mitogen/ssh.py @@ -68,10 +68,10 @@ def filter_debug(stream, it): while buf: if state == 'start_of_line': if len(buf) < 8: - # short read near the buffer limit, block waiting for at - # least 8 bytes so we can discern either a debug line, or - # the minimum desired interesting token from above - # ('password'). + # short read near buffer limit, block awaiting at least 8 + # bytes so we can discern a debug line, or the minimum + # interesting token from above or the bootstrap + # ('password', 'MITO000\n'). break elif buf.startswith(DEBUG_PREFIXES): state = 'in_debug' @@ -229,7 +229,7 @@ class Stream(mitogen.parent.Stream): for buf in filter_debug(self, it): LOG.debug('%r: received %r', self, buf) - if buf.endswith('EC0\n'): + if buf.endswith(self.EC0_MARKER): self._router.broker.start_receive(self.tty_stream) self._ec0_received() return diff --git a/mitogen/su.py b/mitogen/su.py index 2cc3406b..ce81eed5 100644 --- a/mitogen/su.py +++ b/mitogen/su.py @@ -97,7 +97,7 @@ class Stream(mitogen.parent.Stream): for buf in it: LOG.debug('%r: received %r', self, buf) - if buf.endswith('EC0\n'): + if buf.endswith(self.EC0_MARKER): self._ec0_received() return if any(s in buf.lower() for s in self.incorrect_prompts): diff --git a/mitogen/sudo.py b/mitogen/sudo.py index 5d2911fc..32287f9f 100644 --- a/mitogen/sudo.py +++ b/mitogen/sudo.py @@ -168,7 +168,7 @@ class Stream(mitogen.parent.Stream): for buf in it: LOG.debug('%r: received %r', self, buf) - if buf.endswith('EC0\n'): + if buf.endswith(self.EC0_MARKER): self._ec0_received() return elif PASSWORD_PROMPT in buf.lower():