Mitogen Documentation
repository·master·Indexed 25 days ago
https://github.com/mitogen-hq/mitogenA high-performance Python library designed to improve the efficiency and speed of Python execution, specifically for optimizing SSH-based automation and parallel task execution. It provides a Router API to construct execution contexts via SSH, sudo, Docker, kubectl, podman, buildah, and local subprocesses, allowing users to execute Python functions and system commands on remote hosts without complex shell scripting.
What's inside Mitogen
- Mitogen provides internal APIs for users who need to modify or extend the library. Note that these APIs are subject to rapid change, even across minor releases. Use these components to build custom connection types, custom import mechanisms, or specialized process management logic.
How disconnect propagation and error handling works
masterTo prevent contexts from hanging indefinitely when a remote connection fails, Mitogen implements a disconnect propagation mechanism.
The Disconnect Flow
- Tracking:
mitogen.core.Routerrecords the destination context ID of every message received on a stream. - Detection: When a
DEL_ROUTEmessage is generated or received,mitogen.parent.RouteMonitoridentifies every stream that previously communicated with that route. - Notification: The
DEL_ROUTEhandler finds anymitogen.core.Contextin the local process corresponding to the disappearing route and fires adisconnectedevent on it. - Recovery: Consumers (such as
mitogen.core.Receiver) can subscribe to thedisconnectedevent to abort threads that are waiting for replies from the disconnected context.
- Tracking:
Concurrency and deduplication in Mitogen imports
masterMitogen ensures that duplicate
GET_MODULErequests are never issued to a parent. Each layer in the context tree deduplicates requests and synchronizes local threads and descendants onLOAD_MODULEresponses.- Local Threads:
mitogen.core.Importerexecutes under the runtime importer lock. It checks for cached source or in-flightGET_MODULErequests. If none exist, it starts a request and waits via a callback. - Child Requests: When a
GET_MODULEis received from a child,mitogen.master.ModuleForwarderchecks for cached source or in-flight requests to the parent. Once the source arrives, it issuesLOAD_MODULEmessages to the child, including any required dependencies.
- Local Threads:
How Mitogen ensures message authenticity and trust
masterMitogen implements a trust chain to prevent unauthorized message injection (e.g., a downstream context attempting to impersonate the master).
Source Verification
Before dispatching a message,
mitogen.core.Routerperforms a verification step:- It looks up the
mitogen.core.Streamthat should be used to send responses to the context ID listed in the message'sauth_idfield. - If the stream used to receive the message does not match the expected stream for that
auth_id, the message is discarded and a warning is logged.
auth_idvssrc_idauth_id: Used for security and trust. It allows privileged functionality likeCALL_FUNCTION <mitogen.core.CALL_FUNCTION>to make trust decisions. It can be used to grant privileges to contexts that do not follow the natural tree hierarchy (e.g., siblings communicating or amitogen.unixclient connecting to an existing tree).src_id: Represents the actual source ID of the message.
- It looks up the
How the Mitogen Module Importer works
masterThemitogen.core.Importerintercepts Pythonimportstatements viasys.meta_path. When a module is requested, the importer initiates an RPC to the parent context using aGET_MODULErequest to fetch the source code. If the parent does not have the module, the request is forwarded upstream, avoiding duplicate requests for the same module across threads and child contexts.Design principles for Mitogen programs
masterWhen writing programs that span multiple hosts and privilege domains with Mitogen, follow these principles:
- Handle Asynchrony: Expect communication to fail at any moment due to network unreliability. Design for unexpected failures.
- Assume Untrusted Data: A parent must always assume data received from a child is suspect. Never base privileged control decisions (like forming a command to execute) on strings received from a child.
- Separate Program and Data: Avoid Python idioms that rely on manipulating functions or closures as data (e.g., passing a
lambdathat is closed over local program state). This is difficult and unsafe in a distributed environment.
How message routing works in Mitogen
masterMitogen uses a tree-based routing system to facilitate communication between contexts. Routing relies on the
mitogen.core.Routerto find paths between context IDs.Routing Logic
When a
mitogen.core.Routerreceives a message, it attempts to route it using the following priority:- Direct Match: If a stream is directly connected to the target ID, the message is forwarded down that stream.
- Explicit Route: If the master has sent an
ADD_ROUTE <mitogen.core.ADD_ROUTE>message associating a stream with a target ID, the message is forwarded down that stream. - Upward Propagation: If no direct or explicit route is found, the message is forwarded up to the immediate parent. This continues recursively until a parent is reached that knows how to route the message down the tree.
Route Management
- Establishing Routes: When a parent creates a new child, it sends an
ADD_ROUTE <mitogen.core.ADD_ROUTE>message towards its parent. This propagates recursively up to the root. - Route Cleanup: If a stream is disconnected, parents trigger
DEL_ROUTEmessages that propagate upstream for every route associated with that stream. - Ordering Guarantee: Because Mitogen streams are strictly ordered, a parent will always receive the
ADD_ROUTEmessage describing how to reply to a new child before it receives any messages from that child.
How Import Preloading reduces network round-trips
masterMitogen optimizes imports by scanning module bytecode for
IMPORT_NAMEopcodes to identify dependencies. It then pre-loads these dependencies into the child context usingLOAD_MODULEmessages before sending the requested module, reducing latency.Optimization Scenarios:
- Package Requests: If a child requests a package (e.g.,
django), the master identifies dependencies within that package (e.g.,django.utils) that are likely missing in the child and pre-loads them. This can turn 4 round-trips into 1. - Sub-module Requests: If a child has already loaded a package, and subsequently requests a sub-module (e.g.,
django.db), the parent pre-loads all known missing dependencies of that sub-module. This can turn 17+ round-trips into 1.
- Package Requests: If a child requests a package (e.g.,
How Mitogen bootstraps remote Python processes
masterMitogen achieves remote execution without pre-installed software by using a multi-stage bootstrapping process:
- The UNIX First Stage: A small,
zlib-compressed, and base64-encoded Python command is sent to the host. This command executesmitogen.parent.Connection._first_stageto handle decompression and setup. - Forking: The first stage forks. The parent re-executes Python with a clean
argv[0]and connects itsstdinto a UNIX pipe. The child handles the decompression of the actual Mitogen payload. - Bootstrap Payload: The payload contains the source code for
mitogen.core, optimized viamitogen.master.minimize_source(stripping docstrings and comments) to reduce size. - Synthetic Package Generation: Once
mitogen.coreis loaded, Mitogen rearrangessys.modulesto create a syntheticmitogenpackage. It also deletessys.modules['__main__']so that remote imports of the master's__main__module are correctly satisfied. - Environment Setup: The child configures logging (matching the master's level), installs a custom
mitogen.core.Importerintosys.meta_path, and redirectsstdin/stdout/stderrusingmitogen.core.IoLoggerto prevent subprocesses from corrupting the communication stream.
- The UNIX First Stage: A small,
Understand the Router class
masterMitogen uses
Routerclasses to manage communication paths. There are different implementations of the Router depending on the component's role in the architecture:mitogen.core.Router: The base router implementation.mitogen.parent.Router: A router used by parent processes to manage child connections.mitogen.master.Router: A router used by the master process, which can be initialized with abroker(e.g.,mitogen.master.Router(broker=None)).
Use Mitogen signals for component decoupling
masterMitogen uses a simplistic signal mechanism to decouple components. When an instance fires a signal, registered callback functions are executed.
WARNING: Signals execute on the Broker thread and do not have exception handling. User-defined signal handlers should be extremely careful; bugs in these handlers can cause crashes or hangs that prevent the broker from forwarding logs or ensuring a clean shutdown.
How Mitogen avoids negative imports
masterIn Python 2.x, relative imports can cause many 'negative imports' (requests for modules that do not exist, e.g.,
mypkg.sysinstead ofsys), leading to unnecessary network round-trips.To solve this, when a package is imported, the master sends a list of child modules known to exist. The
mitogen.core.Importerchecks if a requested module belongs to a known package; if it does, it ignores the request if the module is not in the provided enumeration of child modules.