Commit Graph

910 Commits (aa15975ad464ffcc4d4e2d267f6171b6c552e6ec)

Author SHA1 Message Date
David Wilson 2fede49078 service: clean up log messages, especially at shutdown 5 years ago
David Wilson 75d179e4b9 remove unused imports flagged by lgtm 5 years ago
David Wilson 45a3014fd4 parent: decode logged stdout as UTF-8. 5 years ago
David Wilson 3b000c7d15 unix: include more IO in the try/except for connection failure 5 years ago
David Wilson 108015aa22 ansible: gracefully handle failure to connect to MuxProcess
It's possible to hit an ugly exception during early CTRL+C
5 years ago
David Wilson 1fca0b7a94 [linear2] fix MuxProcess test fixture and some merge fallout 5 years ago
David Wilson e93762b3db service: avoid taking another lock in the usual case 5 years ago
David Wilson 50bfe4c746 service: don't acquire lock when pool already initialized 5 years ago
David Wilson f4709b1dc2 profiler: marginal improvements 5 years ago
David Wilson 3b585b841e core: ensure 'exit' signal fires even on Broker crash. 5 years ago
David Wilson d6faff06c1 core: wake Waker outside of lock.
Given:

- Broker asleep in poll()
- thread B calling Latch.put()

Previously,

- B takes lock,
- B wakes socket by dropping GIL and writing to it
- Broker wakes from poll(), acquires GIL only to find Latch._lock is held
- Broker drops GIL, sleeps on futex() for _lock
- B wakes, acquires GIL, releases _lock
- Broker wakes from futex(), acquires lock

Now,

- B takes lock, updates state, releases lock
- B wakes socket by droppping GIL and writing to it
- Broker wakes from poll(), acquires GIL and _lock
- Everyone lives happily ever after.
5 years ago
David Wilson 807cbef9ca core: wake Latch outside of lock.
Given:

- thread A asleep in Latch._get_sleep()
- thread B calling Latch.put()

Previously,

- B takes lock,
- B wakes socket by dropping GIL and writing to it
- A wakes from poll(), acquires GIL only to find Latch._lock is held
- A drops GIL, sleeps on futex() for _lock
- B wakes, acquires GIL, releases _lock
- A wakes from futex(), acquires lock

Now,

- B takes lock, updates state, releases lock
- B wakes socket by droppping GIL and writing to it
- A wakes from poll(), acquires GIL and _lock
- Everyone lives happily ever after.
5 years ago
David Wilson 7e51a93231 core: remove old blocking call guard, it's in the wrong place
It should have been in Receiver.get(). Placing it here prevents
*_async() method calls from broker thread.
5 years ago
David Wilson 9035884c77 ansible: abstract worker process model.
Move all details of broker/router setup out of connection.py, instead
deferring it to a WorkerModel class exported by process.py via
get_worker_model(). The running strategy can override the configured
worker model via _get_worker_model().

ClassicWorkerModel is installed by default, which implements the
extension's existing process model.

Add optional support for the third party setproctitle module, so
children have pretty names in ps output.

Add optional support for per-CPU multiplexers to classic runs.
5 years ago
David Wilson 6b8a7cbcc4 [stream-refactor] parent: fix crash on graceful shutdown
Now it's possible for stream.protocol to not refer to MitogenProtocol,
move the signal handler to a MitogenProtocol subclass instead.

Fixes a crash where CTRL+C during child bootstrap would print
AttributeError.
5 years ago
David Wilson 2ccdeeeb87 parent: tidy up create_socketpair() 5 years ago
David Wilson c0513425ca core: more concise Side.repr. 5 years ago
David Wilson f45d8eae66 [stream-refactor] replace cutpaste with Stream.accept() in mitogen.unix 5 years ago
David Wilson 1843f183a3 [stream-refactor] fix flake8 errors 5 years ago
David Wilson c02358698b [stream-refactor] don't abort Connection until all buffers are empty 5 years ago
David Wilson 93342ba60c Normalize docstring formatting 5 years ago
David Wilson 4e6aadc40a [stream-refactor] fix LogHandler.uncork() race
During early initialization under hackbench, it is possible for Broker
to be in LogHandler._send() while the main thread has already destroyed
_buffer. So we must synchronize them, but only while the handler is
corked.
5 years ago
David Wilson 90c989ee59 [stream-refactor] BufferedWriter must disconenct Stream, not Protocol
Fix a race where if Stream.on_receive() detects disconnect, it calls
Stream.on_disconnect(), which fires Stream 'disconnect' event, whereas
if BufferedWriter.on_transmit() detects disconnect, it called
Protocol.on_disconnect(), which did not fire the Stream 'disconnect'
event.

Since mitogen.parent listens on Stream's 'disconnect' event to reap
children, this was causing a very difficult to trigger test failure.

Triggered after <1000 runs on a Xeon E5530 with hyperthreading using
hackbench running at the same priority:

    $ hackbench -s 1048576 -l 100000000000 -g 4
5 years ago
David Wilson 65e31f63fe [stream-refactor] fix Py2.4 failure by implementing missing Timer method 5 years ago
David Wilson 11ae6f3873 core: better Side attribute docstrings 5 years ago
David Wilson fdf3484a2a [stream-refactor] 3.x socket.send() requires bytes 5 years ago
David Wilson c09bbdc2f9 [stream-refactor] fix 2.4 syntax error. 5 years ago
David Wilson b1379e6f45 [stream-refactor] send MITO002 earlier
Prevents 2.4 bootstrap from attempting to fetch os_fork too early.

Connection(None).connect(): pid:25098 stdin:81 stdout:81 stderr:79
ssh.localhost:2201: (partial): mitogen__has_sudo_nopw@localhost's password:
ssh.localhost:2201: (password prompt): mitogen__has_sudo_nopw@localhost's password:
ssh.localhost:2201: (unrecognized): mitogen__has_sudo_nopw@localhost's password:
BootstrapProtocol(ssh.localhost:2201): first stage started succcessfully
BootstrapProtocol(ssh.localhost:2201): first stage received bootstrap
ssh.localhost:2201: (partial): MIdmitogen.os_fork
ssh.localhost:2201: (unrecognized partial): MIdmitogen.os_fork
ssh.localhost:2201: failing connection due to TimeoutError(u'Failed to setup connection after 10.00 seconds',)
5 years ago
David Wilson 4eecc08047 [stream-refactor] merge stdout+stderr when reporting EofError
Fixes sudo regression
5 years ago
David Wilson 1d2bfc28da [stream-refactor] fix crash in detach() / during async/multiple_items_loop.yml 5 years ago
David Wilson 93abbcaf7a [stream-refactor] fix crash in runner/forking_active.yml 5 years ago
David Wilson 6e33de7cd2 unix: ensure mitogen.context_id is reset when client disconnects
To ensure a test process can successfully recreate an Ansible
MuxProcess, reset fork-inherited globals during disconnection.

There is basically no good place for this. Per the comments on #91, it
would be far better if the context's identity was tied to its router,
rather than some global variable.
5 years ago
David Wilson 7c4621a010 [stream-refactor] make syntax 2.4 compatible 5 years ago
David Wilson 0ff5fb8fc4 [stream-refactor] fix su_test failure (issue #363) 5 years ago
David Wilson 8769c3ce24 [stream-refactor] more readable log string format 5 years ago
David Wilson d411003b64 [stream-refactor] dont doubly log last partial line 5 years ago
David Wilson 1069ca43d6 [stream-refactor] port mitogen.buildah, added to master since work began 5 years ago
David Wilson 26b6333787 [stream-refactor] fix unix.Listener construction 5 years ago
David Wilson 1fb3852fa6 [stream-refactor] fix crash when no stderr present. 5 years ago
David Wilson 4b0870aa6e [stream-refactor] fix Process constructor invocation 5 years ago
David Wilson f039c81bb0 [stream-refactor] rename Process attrs, fix up more create_child_test 5 years ago
David Wilson acade4ce88 ssh: fix issue #271 regression due to refactor, add test. 5 years ago
David Wilson 8d1b01d8ef Refactor Stream, introduce quasi-asynchronous connect, much more
Split Stream into many, many classes

  * mitogen.parent.Connection: Handles connection setup logic only.
    * Maintain references to stdout and stderr streams.
    * Manages TimerList timer to cancel connection attempt after
      deadline
    * Blocking setup code replaced by async equivalents running on the
      broker

  * mitogen.parent.Options: Tracks connection-specific options. This
    keeps the connection class small, but more importantly, it is
    generic to the future desire to build and execute command lines
    without starting a full connection.

  * mitogen.core.Protocol: Handles program behaviour relating to events
    on a stream. Protocol performs no IO of its own, instead deferring
    it to Stream and Side. This makes testing much easier, and means
    libssh can reimplement Stream and Side to reuse MitogenProtocol

  * mitogen.core.MitogenProtocol: Guts of the old Mitogen stream
    implementtion

  * mitogen.core.BufferedWriter: Guts of the old Mitogen buffered
    transmit implementation, made generic

  * mitogen.core.DelineatedProtocol: Guts of the old IoLogger, knows how
    to split up input and pass it on to a
    on_line_received()/on_partial_line_received() callback.

  * mitogen.parent.BootstrapProtocol: Asynchronous equivalent of the old
    blocking connect code. Waits for various prompts (MITO001 etc) and
    writes the bootstrap using a BufferedWriter. On success, switches
    the stream to MitogenProtocol.

  * mitogen.core.Message: move encoding parts of MitogenProtocol out to
    Message (where it belongs) and write a bunch of new tests for
    pickling.

  * The bizarre Stream.construct() is gone now, Option.__init__ is its
    own constructor. Should fix many LGTM errors.

* Update all connection methods:  Every connection method is updated to
  use async logic, defining protocols as required to handle interactive
  prompts like in SSH or su. Add new real integration tests for at least
  doas and su.

* Eliminate manual fd management: File descriptors are trapped in file
  objects at their point of origin, and Side is updated to use file
  objects rather than raw descriptors. This eliminates a whole class of
  bugs where unrelated FDs could be closed by the wrong component. Now
  an FD's open/closed status is fused to it everywhere in the library.

* Halve file descriptor usage: now FD open/close state is tracked by
  its file object, we don't need to duplicate FDs everywhere so that
  receive/transmit side can be closed independently. Instead both sides
  back on to the same file object. Closes #26, Closes #470.

* Remove most uses of dup/dup2: Closes #256. File descriptors are
  trapped in a common file object and shared among classes. The
  remaining few uses for dup/dup2 are as close to minimal as possible.

* Introduce mitogen.parent.Process: uniform interface for subprocesses
  created either via mitogen.fork or the subprocess module. Remove all
  the crap where we steal a pid from subprocess guts. Now we use
  subprocess to manage its processes as it should be. Closes #169 by
  using the new Timers facility to poll for a slow-to-exit subprocess.

* Fix su password race: Closes #363. DelineatedProtocol naturally
  retries partially received lines, preventing the cause of the original
  race.

* Delete old blocking IO utility functions
  iter_read()/write_all()/discard_until().

Closes #26
Closes #147
Closes #169
Closes #256
Closes #363
Closes #419
Closes #470
5 years ago
David Wilson 37beb3a5c5 core: teach iter_split() to break on callback returning False. 5 years ago
David Wilson 33ecc8a5d2 issue #507: log fatal errors to syslog.
Next round should log entire exception text, but this is useful enough
already.
5 years ago
David Wilson 46ebd56c7a core/master: docstring, repr, and debug log message cleanups
Debug output is vastly more readable now.
5 years ago
David Wilson 0f7bbcece9 parent: remove unused Timer parameter. 5 years ago
David Wilson f66611dc83 parent: docstring improvements, cfmakeraw() regression. 5 years ago
David Wilson c7ebb39ad4 core: introduce Protocol, DelimitedProtocol and BufferedWriter.
They aren't wired in yet as of this commit, and continue duplicating
other code.
5 years ago
David Wilson d368971749 core: introduce mitogen.core.pipe()
It's used in later commit. This is an os.pipe() wrapper that traps the
file descriptors in a file object, to ensure leaked objects will
eventually be collected, and a central place exists to track open/closed
status.
5 years ago