Commit Graph

668 Commits (5ffaa693a64f23508047dee01425fd0485d95a24)

Author SHA1 Message Date
David Wilson 336e90c5e3 parent: avoid needless quoting in Argv.
This just makes debug output a little more readable.
6 years ago
napkindrawing 745d72bb1d core: support for "doas" become_method 6 years ago
David Wilson 1c5a03bfa5 Bump version for release. 6 years ago
David Wilson 9a453d4753 Bump version for release. 6 years ago
David Wilson 4122fa4a46 debug: give dump_to_logger() thread a name. 6 years ago
David Wilson 894926cf61 docs: add initial release notes. 6 years ago
David Wilson 692275064b parent: fix TtyLogger str/unicode crash on 3.x. 6 years ago
David Wilson 038f8d5dec master: fix another case where built-in module loader throws ImportError
requests/packages.py just imports urllib3 normally, then makes up new
names for it. pkgutil can't cope with that, and returns the loader
(builtin) for the requests package. The built-in loader obviously can't
find_module() for "requests/packages/urllib3/contrib/pyopenssl" because
it doesn't exist on disk.
6 years ago
David Wilson 3a8ea930d7 core: fix NameError in Latch.put(), FileService exception 6 years ago
David Wilson 5da371c5dd service: fix UnboundLocalError. 6 years ago
David Wilson 484d4fdb74 core: fix Latch socket sharing race.
If thread A is about to wake as thread B is about to sleep, and A loses
the GIL at an inopportune moment, it was possible for two latches to
share the same socketpair, causing wakeups routed to the wrong latch.

The pair was returned to the 'idle sockets' list before .recv() had been
called. This manifested as TimeoutError() thrown rarely with many active
threads and the host is heavily loaded (such as Travis CI).

Add more documentation and stop writing single wake bytes. Instead the
recipient's identity is written instead, making it simpler to detect
future bugs.
6 years ago
David Wilson b92545e61a minify: avoid cStringIO use.
On 2.7 it was "accidentally fine" because the buffer object the StringIO
was initialized from happened to look like ASCII, but in 2.6 either
UCS-2 or UCS-4 is used for that buffer, and so the result was junk.

Just use the io module everywhere if we can, falling back to pure-Python
StringIO for Python<2.6.
6 years ago
David Wilson 29f15c236c core: remove needless size prefix from core_src_fd.
I think this is brainwrong held over from an early attempt to write the
duplicate copy of core_src on stdin.
6 years ago
David Wilson 04e138e060 core: fix serialization of empty bytes() on 3.x. 6 years ago
David Wilson ff2f44b046 core: reduce chance of Latch.read()/write()/close() race.
Previously it was possible for a thread to call Waker.defer() after
Broker has torns its Waker down, and the underlying file descriptor
reallocated by the OS to some other component.

This manifested as latches of a subsequent test invocation receiving the
waker byte (' ') rather than their expected byte '\x7f'.

This doesn't fix the problem, it just significantly reduces the chance
of it occurring. In future Side.write()/read()/close() must be
synchronized with a lock.

Previously the problem could be reliably triggered with:

    while :; do
        python tests/call_function_test.py -vf CallFunctionTest.{test_aborted_on_local_broker_shutdown,test_aborted_on_local_context_disconnect}
    done
6 years ago
David Wilson e24eddb1ce core: move Latch docs back inline. 6 years ago
David Wilson 42276f158b core: log the data received on the latch file handle. 6 years ago
David Wilson 970f54de85 service: remove stray debug 6 years ago
David Wilson caa648b1ea utils: handle duplicate log_to_file() calls. 6 years ago
David Wilson 8791d40081 parent: tidy up call_async() logging. 6 years ago
David Wilson 4ff47d6a93 parent: more 2/3x format fixes 6 years ago
David Wilson a52064a24f core: reordered find_module() test was broken (again)
e81b3bd0652b5eb125eb224ceca281b9d540dd5e

The whitelist check must happen /after/ the other checks, otherwise we
unconditionally retunr self for crap like 'ansible.module_utils.json'.
6 years ago
David Wilson 24ecfb3b13 Fix setns.py syntax for 3.x 6 years ago
David Wilson 9e3e02fb65 tokenize must parse under 3.x even if it won't run there
To support 3.x parent 2.x child
6 years ago
David Wilson 6b4e047017 tests: 3.x parent_test fixes. 6 years ago
David Wilson 6cbf34d5fe tests: another smattering of 3.x type/API fixes. 6 years ago
David Wilson 0422a8c263 parent: python_path setting depends on local or remote
For local, we want to default to the same Python version as the current
process. For remote, we want whatever is on offer.
6 years ago
David Wilson db529e8228 core: fix Receiver.__iter__ regression on EOF 6 years ago
David Wilson 0eb77b5f7c utils: always enable microsecond logging.
It's too useful, and the logs are fairly out of control already, may as
well just capture everything in the first pass.
6 years ago
David Wilson c141dd10ec master: fix resolve_relpath()
looks like this was just as broken on 2.x, and suddenly we're
finding a bunch more legit Django deps. It seems anywhere
absolute_import appeared in 2.x, we skipped some imports.
6 years ago
David Wilson b0404bef40 tests: fix get_module_via_* encoding issues 6 years ago
David Wilson 9903692811 master: update scan_code_imports to cope with wordcode
Constant-sized opcodes were introduced as an optimization in Python 3.6.
See https://bugs.python.org/issue26647
6 years ago
David Wilson 9fb2371d64 importer: reorder/tweak find_module() tests to cope with six.moves
The old hack on the master side we had is broken for some reason on 3.x.
Instead tweak the client to be more selective: if a request is for a
module within a package, the package must be loaded (in sys.modules),
and its __loader__ must be us. Previously if the module didn't exist in
sys.modules, we'd still try to fetch from the master, which doesn't
appear to ever make sense.
6 years ago
David Wilson 410016ff47 Initial Python 3.x port work.
* ansible: use unicode_literals everywhere since it only needs to be
  compatible back to 2.6.
* compat/collections.py: delete this entirely and rip out the parts of
  functools that require it.
* Introduce serializable Kwargs dict subclass that translates keys to
  Unicode on instantiation.
* enable_debug_logging() must set _v/_vv globals.
* cStringIO does not exist in 3.x.
* Treat IOLogger and LogForwarder input as latin-1.
* Avoid ResourceWarnings in first stage by explicitly closing fps.
* Fix preamble_size.py syntax errors.
6 years ago
David Wilson 3a304b2458 issue #275: su: add CentOS 6 style su failure 6 years ago
David Wilson d6126a9516 issue #275: parent/ssh: centralize EC0_MARKER and change it for ssh.py.
Must maintain a minimum buffer length prior to deciding whether we have
an interesting token, and 'EC0' is too short for that.
6 years ago
David Wilson 84fa3ff024 issue #275: ssh: state machine-ish filter_debug() 6 years ago
David Wilson fbd5837cf2 issue #275: parent: use TIOCSCTTY on Linux too.
This appears to be harmless, except for Python 2.6 on Linux/Travis,
where for some reason (some stdlib change?) simply opening the TTY is
insufficient.
6 years ago
David Wilson 60ad75f436 issue #275: Tidier SSH debug logging. 6 years ago
David Wilson e0c116a29f issue #275: logging package uses classic classes in 2.6. 6 years ago
David Wilson cfd2887292 issue #275: default to 'python' for default remote interpreter.
So we get 2.4/2.5/2.6/2.7/3.x.
6 years ago
David Wilson 884a72ee86 issue #277: core: move Darwin versioner check into first stage
The 'versioner.c' dodging check added in 0ef23d86 was wrong, since the
check occurred on the host machine, when the fix actually needs to apply
to the Darwin target.

Fixes ability to target OS X from a Red Hat controller, manifesting as
an error like:

    D mitogen: mitogen.parent.TtyLogStream('local.2472'):  'python(mitogen:dmw@localhost.localdomain:2449): realpath couldn\'t resolve "/usr/bin/python(mitogen:dmw@localhost.localdomain:2449)"'

The "realpath couldn't resolve" error comes from versioner.c:

    https://opensource.apple.com/source/perl/perl-104/versioner/versioner.c
6 years ago
David Wilson 75b195ba4b core: race during Receiver construction.
It's possible for a message to arrive after .add_handler() but before
Latch construction.

This is papering over a bigger problem with service pool instantiation.

https://travis-ci.org/dw/mitogen/jobs/390409832#L2901

    TASK [Spin up a few interpreters] **********************************************
    changed: [target] => (item=1)
    ERROR! [pid 5355] 14:47:50.224945 E mitogen.ctx.ssh.localhost:2201.sudo.mitogen__user2: mitogen: Router(Broker(0x7f1e93911450))._invoke(Message(19100, 19095, 19095, 110, 1005, '\x80\x02U\x1fmitogen.service.PushFileServiceq\x01U\x11store_and_f'..8955)): <bound method Receiver._on_receive of Receiver(Router(Broker(0x7f1e93911450)), 110)> crashed
    Traceback (most recent call last):
      File "<stdin>", line 1471, in _invoke
      File "<stdin>", line 491, in _on_receive
    AttributeError: 'Receiver' object has no attribute '_latch'
6 years ago
dw 27ab051289
Merge pull request #282 from dw/issue278
Issue278
6 years ago
David Wilson 0e958ea177 issue #278: tty logger Side constructed with incorrect Stream
Harmless, but produced the wrong log message prefix.
6 years ago
David Wilson b58603c7a4 issue #278: ssh: support ssh_debug_level option and log TTY output.
Now debug logs may be captured all the way through the connection.
6 years ago
David Wilson 888829544a issue #280: move find_module() log output to IOLOG
It just generates far too much spam, and its final decision is obvious
since a followup load_module() will exist for positive matches.
6 years ago
David Wilson e3482bdd8f ssh: Only match "permission denied" at start of line; closes #271. 6 years ago
David Wilson 2fbe1f1b54 Get integration tests running under 2.6.
Closes #270
Closes #273
6 years ago
David Wilson 205052ed90 service: fix SerializedInvoker CallError handling.
This cutpaste needs refactored. Ensure the caller receives a copy of the
exception.
6 years ago
David Wilson d5c4333b9e debug: functions for triggering EINTR 6 years ago
David Wilson 6377f2d69c issue #257: split pool shutdown and join. 6 years ago
David Wilson e35694acd5 ansible: flake8 fixes. 6 years ago
David Wilson 3909cb11f6 service: recreate the pool after fork. 6 years ago
David Wilson 05e0b134f9 service: simplify CALL_SERVICE stub and fix race.
If PushService.store_and_forward() loses the race to arrive at a brand
new context first, and the context's main thread is already executing a
CALL_FUNCTION that is blocked on the result of PushService, deadlock
could occur in the old scheme.

Instead (for now) simply spam a thread for each incoming message, and
use the get_or_create_pool() lock to ensure things work out in the end.
This could potentially generate a huge number of threads given the wrong
app, but we'll fix that problem when it appears.
6 years ago
David Wilson 92ecf29559 core: check in the hacks that let Ansible work just now. 6 years ago
David Wilson f6d9b074ff master: reduce module verbosity somewhat. 6 years ago
David Wilson 526590027a issue #186: PushFileService improvements.
New method to send all modules and files in one roundtrip.
6 years ago
David Wilson 9e78c20eba core/parent: add Context.call_no_reply(). 6 years ago
David Wilson b3a5fa70b0 core: copy debug setting to child's Router too.
core.Router doesn't pay attention to this attribute, but after
upgrade_router() has been called, the new parent.Router will.
6 years ago
David Wilson 23b2a545cf fork: avoid another logging deadlock at startup.
The very first task /must/ be clearing out logging locks, since
_at_fork() functions call LOG.debug() via Side.close(). Additionally,
the root logger is not included in loggerDict, so we must specify it
explicitly.
6 years ago
David Wilson 785df88fa4 issue #186: core: remove long-forgotten hack.
This is likely to break something, it was definitely needed at some
point, but I never put much effort into figuring out why. Meanwhile,
Python appears to make find_module('ansible.module_utils.facts.')
requests in some circumstances, which causes us to indicate the module
exists while this hack exists.

So remove it, and let's see what breaks.
6 years ago
David Wilson 76beea6554 issue #186: move target._get_file into mitogen.service
For lack of a better place to keep the client function, make it a
classmethod of FileService itself for now.

The old _get_file() is removed in a subsequent commit.
6 years ago
David Wilson a3b747af1b issue #186: add PushFileService
This is like FileService but blocks until the file is pushed by a parent
context, with deduplicating behaviour at each level in the hierarchy. It
does not stream large files, so it is only suitable for small files like
Python modules.

Additionally add SerializedInvoker for use with PushFileService, which
ensures all method calls to a single service occur in sequence.
6 years ago
David Wilson 2e8c027322 issue #213: avoid service.Pool construction race
Ensure concurrent calls to service.Pool do not result in a duplicate
pool being constructed in a child.
6 years ago
David Wilson 34daec4a7a core: prevent warning when CALL_FUNCTION used without reply_to
Such as when the stub CALL_SERVICE handler is used.
6 years ago
David Wilson d9087c510b ansible: move FileService into mitogen.service. 6 years ago
David Wilson b577a11f86 master: fix IdAllocator log messages. 6 years ago
David Wilson f7d2eace08 tests: importer fixes 6 years ago
David Wilson f7b368b1fb master: implement ModuleResponder.forward_module(). 6 years ago
David Wilson 9492dbc4d7 parent: split out minify.py and add stub where master can install it.
This needs a cleaner mechanism to install it, at least this one is
documented.
6 years ago
David Wilson 325d13538f issue #196: debug: don't statically import master. 6 years ago
dw c24d29d367
Merge pull request #255 from dw/dmw
Dmw
6 years ago
David Wilson 3b0addcfb0 service: v2. Closes #213 6 years ago
David Wilson 469bde63c2 parent: fix log message ordering 6 years ago
David Wilson a4ddef25a1 core: move reader/writer debug prints
They stop working with kqueue/epoll poller in the old location. Also
comment them out again, should never have been checked in uncommented.
6 years ago
David Wilson 3f595bbc7e issue #213: use import_module() in parent.py.
This dynamic import crap really needs to be ripped out of parent.py
again. Static imports work much better for the module loader too.
6 years ago
David Wilson e118963b30 issue #254: fork: take care not to rely on FD numbers. 6 years ago
David Wilson fc59f57ba2 issue #213: core: split out import_module() for use in services.py. 6 years ago
David Wilson 49fb25ee1c issue #213: core: fix shutdown crash due to member variable rename 6 years ago
David Wilson 40c6c6426f issue #213: core: fix test breakage due to log message change 6 years ago
David Wilson 2310497d55 issue #213: core: have Message.reply() log msg for zero reply_to
It's easy to call msg.reply() by accident on a message that never had
reply_to set, resulting in a "invalid handle" error message coming from
router. Instead log a more accurate message on the stack that actualy
caused the problem.
6 years ago
David Wilson d2714752ee docs: tidy ups 6 years ago
David Wilson 61365236ad docs/select: fix up more references, fix headings. 6 years ago
David Wilson 4bf3d01104 select: add missing get(block=..) parameter. 6 years ago
David Wilson ddf28987a0 master: split Select() into new module to reduce wire size.
service.py currently imports master.py(+parent.py) just to get Select().
6 years ago
David Wilson 7a592d1c34 core: better Poller.__repr__ 6 years ago
David Wilson b0ce6eecd7 fork: support on_start= argument. 6 years ago
David Wilson 00edf0d66d core: have ExternalContext accept a config dict rather than kwargs.
The parameter lists had gotten out of control.
6 years ago
David Wilson 7d0209d8de issue #249: have upgrade_router() upgrade the poller too.
Now when a child becomes a parent, it gets a new poller suitable for
many more children than was possible using select().
6 years ago
David Wilson 55fff54774 core: make try/catch logic a little clearer in Latch.get() 6 years ago
David Wilson 05a5f2b6e5 core: if Poller.poll() fails, TimeoutError would be raised.
We must check whether poller threw an exception both in the case that we
weren't woken and the case that we were.
6 years ago
David Wilson 5bdc1719c5 issue #249: epoll() raises IOError for EINTR, not select.error. 6 years ago
David Wilson 6d18ce81d8 issue #249: restore duplex behaviour for epoll
With epoll() there is only one kernel-side object per file descriptor,
which is why _control() is such a pain. Since we merge receive/transmit
watching into that single object, we must always test the mask for both
conditions when reading results.

Kqueue isn't/doesn't appear to be like this. The identity of a Kqueue
event is keyed on (fd, filter), and we register a separate event for
both transmit and receive, so the 'elif' in KqueuePoller.poll() does not
appear to need to change.

Previously, a FD marked for read+write would not indicate writeability
until it was no longer readable.
6 years ago
David Wilson 6b98818046 issue #249: epoll distinguishes between hangup and disconnect
..typical Linux, for certain descriptor types only. So our receive mask
must match both, and normalize it into a read event like every other
poller.
6 years ago
David Wilson 07056b0dd1 issue #249: fix ordering bug masked by previous implementation 6 years ago
David Wilson 36a1024861 issue #249: port Latch to poller too.
This is probably going to suck for perf :/
6 years ago
David Wilson 1070dfae72 issue #249: fix iter_read() regression. 6 years ago
David Wilson dcf0aa351e issue #249: whoops, fix new poller timeouts. 6 years ago
David Wilson aa8f786413 issue #249: fix Poller.from_existing() for v2 API 6 years ago
David Wilson 5645629e5d issue #249: the new pollers must handle syscall restarts too. 6 years ago
David Wilson 4df020827d issue #249: explicitly close pollers when done. 6 years ago
David Wilson 9905f6d8b4 issue #249: make write_all() and iter_read() use PREFERRED_POLLER. 6 years ago
David Wilson b6124f8396 issue #249: EpollPoller v2. 6 years ago
David Wilson 9abcf63155 issue #249: Poller API v2 (BSD only).
Now it's BasicStream/Side-agnostic, so it can be reused for Latch and
iter_read().
6 years ago
David Wilson 11c2e4ab3e core: set _v and _vv to True in enable_debug_logging().
router.enable_debug() has been broken for ages.
6 years ago
David Wilson 7320c542df issue #249: EpollPoller() for Linux. 6 years ago
David Wilson bc7be1879d issue #249: initial poller implementation (BSD only) 6 years ago
Daniel Badea 020c8b5013 fix host_keys= exception message 6 years ago
David Wilson d1a22cb5d4 issue #186: parent: implement FORWARD_MODULE.
To support detach, we must be able to preload the target with every
module it will need prior to detachment. This implements the
intermediary part of the process (i.e. the Ansible fork parent) --
receiving LOAD_MODULE/FORWARD_MODULE pairs and ensuring they reach the
child.
6 years ago
David Wilson 78d375e0c5 core: CallError should handle any exception type.
Previously SystemExit would be pickled.
6 years ago
David Wilson def22c226f issue #179: don't reap first stage until core_src_fd is drained.
Bootstrap would hang if (as of writing) a pipe sufficient to hold 42,006
bytes was not handed out by the kernel to the first stage. It was luck
that this didn't manifest before, as first stage could write the full
source and exit completely before reading begun.

It is not clear under which circumstances this could previously occur,
but at least since Linux 4.5, it can be triggered if
/proc/sys/fs/pipe-max-size is reduced from the default of 1MiB, which
can have the effect of capping the default pipe buffer size of 64KiB to
something lower.

Suspicion is that buffer pipe size could also be reduced under memory
pressure, as reference to busy machines appeared a few times in the bug
report.
6 years ago
David Wilson d65e047b12 issue #179: ec0_receive() and connect_bootstrap() should use deadline.
Now there is a single global deadline derived from ansible.cfg timeout=
value.
6 years ago
David Wilson 356647bef4 issue #132: initial unidirectional routing mode. 6 years ago
David Wilson e615265ebd master: make is_stdlib_path() a free function
For Ansible module loader work.
6 years ago
David Wilson a37ccabd91 core: wrapper functions provide no protection in this case 6 years ago
David Wilson cecef992b0 issue #218: core: add Secret and Blob types. 6 years ago
David Wilson 42cc009b60 service: don't sleep on empty Select during shutdown.
Avoids a select error during random CTRL+C.
6 years ago
David Wilson 7f1060f54a issue #186: initial version of subtree detachment. 6 years ago
David Wilson 8bd34e1e28 ansible: gracefully report connection timeouts as StreamError. 6 years ago
David Wilson c0e8b3d60a ssh: error wording was inaccurate. 6 years ago
David Wilson 8fc1eac6ae utils: combine MITOGEN_LOG_LEVEL and MITOGEN_LOG_IO.
Saves lots of readline fiddling.
6 years ago
David Wilson 4d1c6d2101 issue #127: ssh: reasonable solution to host key checking.
Ideally it would be possible to specify a callback function, but this is
not possible for proxied connections. So simply provide the 3 most
useful modes, defaulting to the most secure.

Closes #127. Closes #134.
6 years ago
David Wilson 92a2565507 issue #241: child main thread does not gracefully handle CTRL+C
In Ansible, depending on when CTRL+C is triggered, if it occurs after
the connection multiplexer process has forked, and after it has in turn
forked the "connection: local" context and its corresponding "clean fork
parent", since all the broker processes still belong to Ansible's
terminal foreground process group, they are all capable of receiving
SIGINT in response to CTRL+C being pressed on that terminal.

This papers over the problem. Really we want those KeyboardInterrupts to
be logged, to call setsid() frmo the connection multiplexer process to
isolate it from the terminal foreground process group. That way its only
indication of top-level process shutdown is using the graceful
disconnect mechanism that already exists in process.py::worker_main().
6 years ago
David Wilson 3322eaef45 Basic "su" method. 6 years ago
David Wilson 79346d96db core: Allow dead messages to be delivered regardless of policy 6 years ago
David Wilson f5d22a3ca1 core: support deleting handlers, make Receiver.close() unregister 6 years ago
David Wilson 5e6e56f0c5 issue #212: service: make call_async kwargs optional. 6 years ago
David Wilson afe983d6c9 issue #212: service: support no_reply decorator. 6 years ago
David Wilson bf6c2fa97c issue #212: service: more concise repr 6 years ago
David Wilson ff7fb00569 parent: return latch to wait() caller to allow graceful timeout 6 years ago
David Wilson c0ced6d04a core: fix monster fork FD leak
_sockets only refers to the idle sockets list, it doesn't refer to every
socket currently in use by a Latch, for example, the 2*16 used by e.g.
Ansible's sleeping service pool.
6 years ago
David Wilson 7316c08237 core: fix _tls_init() race.
The GIL could be lost between the check for an empty list and popping a
socket off the list. Previously _tls_init (per its name) used per-thread
storage, hence the bug.
6 years ago
David Wilson fdac4ecce8 setns: typos 6 years ago
David Wilson e93ac2f3a7 debug: implement some basic helpers to debugger. 6 years ago
David Wilson 7c5bbc5168 setns: support changing user.
To match existing third party plugin.
6 years ago
David Wilson 947d35649c parent: note exception machine's hostname.
For dumb situations where user (i.e. me) is trying to fix a problem in
the wrong place.
6 years ago
David Wilson e8b4c4e683 issue #223: implement setns connection type
machinectl does not support any sensible form of pipe to the child
process, so it is necessary to bypass it when talking to a systemd
container (see systemd/systemd#8850).

This can also form the basis for issue #223, where the post-fork
namespace switching dance required to connect to the Pythonless
container will be the same.
6 years ago
David Wilson 3196b6e7f7 Add FreeBSD jail support. 6 years ago
David Wilson b3d352c601 Add lxc container support. 6 years ago
David Wilson 1be03eb458 parent: change create_child interface.
To allow for additional arguments.
6 years ago
David Wilson 1fc7df5be5 Move canonical library version to __init__.py. 6 years ago
David Wilson 6fb3a76e68 master: annotate LogForwarder messages.
mitogen/master.py:
    Annotate forwarded log entries with their original source, logger
    name, and message.

ansible:
    mark stderr in red with -vvv

    Tempting to make this appaer 100% of the time, but some crappy
    bashrcs may cause lots of junk to be printed.
6 years ago
David Wilson 9d0949eb99 docker: fixes & add username parameter. 6 years ago
David Wilson e63ae4768e core: support Receiver.get(thread_dead=False)
For tests.
6 years ago
David Wilson 509ef14121 service: add an on_shutdown() callback. 6 years ago
David Wilson 4c5e13bf87 core: add Stream.pending_bytes() accessor. 6 years ago
David Wilson 7c88e4d013 Move _DEAD into header, autogenerate dead messages
This change blocks off 2 common scenarios where a race condition is
upgraded to a hang, when the library could internally do better.

* Since we don't know whether the receiver of a `reply_to` is expecting
  a raw or pickled message, and since in the case of a raw reply, there
  is no way to signal "dead" to the receiver, override the reply_to
  field to explicitly mark a message as dead using a special handle.

  This replaces the serialized _DEAD sentinel value with a slightly
  neater interface, in the form of the reserved IS_DEAD handle, and
  enables an important subsequent change: when a context cannot route a
  message, it can send a generic 'dead' reply back towards the message
  source, ensuring any sleeping thread is woken with ChannelError.

  The use of this field could potentially be extended later on if
  additional flags are needed, but for now this seems to suffice.

* Teach Router._invoke() to reply with a dead message when it receives a
  message for an invalid local handle.

* Teach Router._async_route() to reply with a dead message when it
  receives an unroutable message.
6 years ago
David Wilson e56608ab91 parent: don't wait for SIGTERM to complete. 6 years ago
David Wilson cbe6be449e issue #201: parent: log a warning and work around race for now. 6 years ago
David Wilson 9fe14e841c parent: reap the child process if connection fails
For example if no response is received in :attr:`connect_timeout`
seconds, the child would be left running.
6 years ago
David Wilson 296683b130 ansible: always display Mitogen errors and warnings.
They're no longer buried in -vvv output.
6 years ago
David Wilson 65fb6ff9fe issue #195: comment out stack pruning code 6 years ago
David Wilson 810f557514 issue #195: MITOGEN_DUMP_THREAD_STACKS=1 6 years ago
David Wilson f06ae05734 issue #195: add extra logging around FileService and get_file(). 6 years ago
David Wilson 46a311165e issue #148: parent: prevent race in iter_read()
There is no guarantee on the ordering select() returns file descriptors.
So if, e.g. in the case of sudo_nonexistent.yml, sudo prints an error
to a single FD before exitting, there was previously no gurantee
iter_read() would read off the error before failing due to detecting
disconnect on any FD.

Now instead we keep reading while any non-disconnected FD exists.
6 years ago
David Wilson e43c6c531b Mostly implement hybrid TTY/socket mode for sudo and SSH.
Presently there is still no mechanism to add :attr:`tty_stream` to the
multiplexer after connection is successful, but for now it's not
expected that anything will be logged to it anyway.

Closes #148.
6 years ago
David Wilson c6284e00e9 Use subprocess to start child processes; closes #185. 6 years ago
David Wilson bdc76c8231 parent: do not attempt to reap child twice. 6 years ago
David Wilson 54452c4015 service: fix UnboundLocalError. 6 years ago
David Wilson 202ce0f641 Prevent construction of unicode Message.data
And fix one case of it in parent.py.
6 years ago
David Wilson c83b113600 service: log better warning when CallError raised. 6 years ago
David Wilson ce6fb05d87 tests: 'fix' responder test.
Needs a complete rewrite, but this will do for now.
6 years ago
David Wilson f9eb66e76e _py_filename() must handle None too. 6 years ago
David Wilson 34a1e3337f Fix get_module_via_sys_modules when running under unit2. 6 years ago
David Wilson cc980569a3 issue #159: initial context LRU implementation
Now Connection.close() *must* be called in the worker, to ensure the
reference count for a context drops correctly.

Remove 'discriminator' for now, I'm not using it for testing any more
and it complicated this code.

This code is a car crash, it needs rewritten again. Ideally some/most of
this behaviour could live on services.DeduplicatingService somehow, but
I couldn't come up with a sensible design.
6 years ago
David Wilson 4c8ec131f9 issue #16: initial smorgasbord of 3.x fixes. 6 years ago
David Wilson c4bef102fe issue #16: Python 2.4-3.x compatible exception handling. 6 years ago
David Wilson 8889708f24 core: blacklist Jython org.* by default too.
1 silly roundtrip.
6 years ago
David Wilson e5b784ed32 parent: reduce cutpaste
Unclear whether exec() is better or worse than __import__(), but at
least the semantics are correct.
6 years ago
David Wilson 38c0ad1eea core: don't deregister Router handles until Broker exit.
Lots of "invalid handle: ..., 102" messages started appearing during
exit recently because ordering changed slightly, and local handles were
sent _DEAD even though the broker loop was still progressing through
shutdown.

The "shutdown" event is too early to close handles: it is the start of
the grace period where streams and downstream contexts can finish up any
work and deliver buffered data, including FORWARD_LOG messages that
haven't arrived yet.

So instead,

- move the _DEAD logic to the "exit" event,
- get rid of Context.on_shutdown() entirely, it's been unused for over
  a month,
- get rid of the "crash" event, since it always fires prior to "exit",
  and its only use was to send _DEAD to local handles, which now happens
  during exit anyway.
6 years ago
David Wilson 813d139d48 Import v2.7.11 tokenize.py for use on older Pythons; closes #189.
It's worth note that 2.7.10 shipped with Sierra, managed to not notice
this due to using a Homebrew 2.7.14.
6 years ago
David Wilson ec720eab1a Merge commit 'refs/pull/178/head' of github.com:dw/mitogen 6 years ago
David Wilson 3682ac6e29 fork: ensure importer handle is installed on the new router. 6 years ago
David Wilson 3613162bc0 ansible: enable forking when requested and for async jobs.
Closes #105.
References #155.

mitogen/service.py:
    Refactor services to support individually exposed methods with
    different security policies for each method.

    - @mitogen.service.expose() to expose a method and set its policy
    - @mitogen.service.arg_spec() to validate input.
    - Require basic service message format to be a tuple of
      `(method, kwargs)`, where kwargs is always a dict.
    - Update DeduplicatingService to match the new scheme.

ansible_mitogen/connection.py:
    - Rename 'method' to 'method_name' to disambiguate it from the
      service.call()'s method= argument.

ansible_mitogen/planner.py:
    - Generate an ID for every job, sync or not, and fetch job results
      from JobResultService rather than via the initiating function
      call's return value.
    - Planner subclasses now get to select whether their Runner should
      run in a forked process. The base implementation requests this if
      the 'mitogen_isolation_mode=fork' task variable is present.

ansible_mitogen/runner.py:
    Teach runners to deliver their result via JobResultService executing
    in their indirect parent mux process.

ansible_mitogen/plugins/actions/mitogen_async_status.py:
    Split the implementation up into methods, and more compatibly
    emulate Ansible's existing output.

ansible_mitogen/process.py:
    Mux processes now host JobResultService.

ansible_mitogen/services.py:
    Update existing services to the new mitogen.service scheme, and
    implement JobResultService:

    * listen() method for synchronous jobs. planner.invoke() registers a
      Sender with the service prior to invoking the job, then sleeps
      waiting for the service to write the job result to the
      corresponding Receiver.

    * Non-blocking get() method for implementing mitogen_async_status
      action.

    * Child-accessible push() method for delivering task results.

ansible_mitogen/target.py:
    New helpers for spawning a virginal subprocess on startup, from
    which asynchronous and mitogen_task_isolation=fork jobs are forked.
    Necessary to avoid a task inheriting potentially
    polluted/monkey-patched parent environment, since remaining jobs
    continue to run in the original child process.

docs/ansible.rst:
    Add/merge/remove some behaviours/risks.

tests/ansible/integration:
    New tests for forking/async.
6 years ago
Alex Willmer 1bc32adad4 Issue #160: Cache minimize_source()
Before

```
python tests/bench/local.py
0 120.245933533
1 119.300842285
2 118.355035782
3 123.839855194
```

After

```
python tests/bench/local.py
0 66.3640499115
1 65.9508705139
2 72.4799633026
3 65.7958984375
```
6 years ago
Alex Willmer 0b46b90c62 Issue #160: Apply 2.x workarounds to lru_cache backport
all() was introduced in Python 2.5
with: blocks arrived in Python 2.6
nonlocal and default utf-8 source encoding were added in Python 3.x
6 years ago
Alex Willmer fc0fb732a3 Issue #160: Vendorize namedtuple and lru_cache
namedtuple from
https://hg.python.org/cpython/file/3f79ecab5e52/Lib/collections.py
(Python 2.6)

lru_cache from
937ac1fe06/Lib/functools.py
Python 3.5
6 years ago
Alex Willmer dc3f5730a2 Merge branch 'master' into eye-of-the-token-its-the-thrill-of-the-light 6 years ago
David Wilson f655be1455 ssh: fix password prompt check when running with -vvv
Can only happen by hacking -vvv into ssh.py at present, but that will
probably be exposed via a constructor parameter in future.
6 years ago
David Wilson cd098ef158 issue #183: re-raise StreamError in calling context.
This allows catching just StreamError regardless of via=None or
via=<context>. Deserves a more general solution, but it's easy to fix up
later.
6 years ago
David Wilson 998a1209cc issue #183: make PasswordErrors subclass of StreamError. 6 years ago
David Wilson f6d436783c issue #106: add Service.__repr__, reply to bad calls
* Don't hang callers that fail validate_args(), instead tell them their
  message was rejected.
* Add Service.repr for nicer logging.
6 years ago
David Wilson 8f175bf7a8 issue #106: _unpickle_context() did not allow nameless contexts.
These are generated by any child calling .context_by_id() without
previously knowing the context's name, such as Contexts set in
ExternalContext.master and ExternalContext.parent.
6 years ago
David Wilson 17bfb596d0 issue #106: mitogen.service missing from modules list. 6 years ago
David Wilson 504032e6e8 issue #106: has_parent_authority should accept own context ID.
When a stream (such as unix.connect()) has its auth_id set to the
current context's, we should allow those requests too, since the request
is working with the privilege of the current context.
6 years ago
Alex Willmer 48623763d6 minimize_source: Implement reindentation 6 years ago
Alex Willmer 556ee2aec6 minimize_source: Handling indentation
In the case that string(s) are replaced, any indent or dedent tags must
be re-inserted after the replacemnts.
6 years ago
Alex Willmer a1e9b9e8db Issue #160: Reimplement minimize_source as token filters
Benefits:

- More correct than re.sub()
- Better handling of trailing whitespace
- Recognises doc-strings regardless of quoting style

Limitations:

- Still not entirely correct
  - Creates a syntax error when function/class body is only a docstring
  - Doesn't handle indented docstrings yet
- Slower by 50x - 8-10 ms vs 0.2 ms for re.sub()
  - Not much scope for improving this, tokenize is 100% pure Python
- Complex state machine, harder to understand
- Higher line count in parent.py
- Untested with Mitogen parent on Python 2.x and child on Python 2.x+y

No change

- Only requires Python stdlib modules
6 years ago
David Wilson fa271fcc8e issue #174: select.error interface differs to OSError
Only OSError got the magical attribute treatment, select.error still
behaves like a tuple.
6 years ago
David Wilson ffdd192397 issue #155: must catch select.error too.
Regression caused by merging exception handlers in 9079176.
6 years ago
David Wilson bbb0f1bbd8 issue #155: fix double-fork behaviour and test it this time. 6 years ago
David Wilson 6670cba41c Introduce handler policy functions; closes #138.
Now you can specify a function to add_handler() that authenticates the
message header, with has_parent_authority() and is_immediate_child()
built in.
6 years ago
David Wilson 46a14d4ae2 core: Fix logging crash if data is non-string. 6 years ago
David Wilson 40b978c9b7 core: Fix source verification.
Previously:

* src_id could be spoofed
* auth_id was checked but the message was still delivered!
6 years ago
David Wilson fe614aa966 core: cleanup handlers on broker crash; closes #112. 6 years ago
David Wilson 29e508fde9 ssh: enable app-level keepalive by default; closes #77 6 years ago
David Wilson 1ff27ada49 Add maximum message size checks. Closes #151. 6 years ago
David Wilson e1af2db4ae issue #155: handle crash in the forking child better.
This code path is probably only necessary during development, but it
prevents tracebacks (etc.) getting written over the Stream socket, which
naturally causes corruption.

Instead keep whatever the parent has for stderr, manually write a
traceback there and hard exit.
6 years ago
David Wilson 6db3588c93 Only call _start_transmit when required; closes #165. 6 years ago