This is an Infinidat project.
infi.blocking runs a Python callable in a separate local process and
returns its result or re-raises its exception in the caller. The public entry
point is make_blocking; lower-level context managers are available for
applications that want to reuse a worker.
The parent and worker communicate over an authenticated loopback connection.
No external RPC framework is required. Install the gevent extra when RPC
waits must yield to a gevent event loop. The former gevent_rpc extra name
remains available as a compatibility alias.
Control and logging traffic use separate authenticated channels. The logging channel keeps one connection open for the lifetime of the worker, while control calls remain independently bounded by their configured timeouts. RPC method arguments and return values are not written to transport debug logs. Output written explicitly by an application callable is application data and must still be treated accordingly.
RPC I/O uses one monotonic deadline for connection establishment,
authentication, request writes, and response reads. Partial headers/bodies and
backpressure do not restart that deadline. Authentication also has its own
five-second upper bound for the complete exchange, before any unpickling.
The transport retains the standard library's multiprocessing.Connection
framing and serialization, with interruptible socket read/write hooks. CPU
time inside application serialization or callbacks is not preempted by an
I/O timeout.
Stopping a server interrupts its socket waits, including an idle persistent
connection, an incomplete authentication exchange, and a blocked response
write. It does not need a second RPC connection. The serving thread owns and
closes its sockets; socket waits use cancellation polling intervals of at most
50 ms. A callback already executing is not forcibly terminated: if it does
not return within the shutdown timeout, TransportTimeout is raised.
When a client call fails, completed transport/serialization traceback frames are cleared, including chained exceptions, and active RPC boundary frames drop their payload arguments. Exception types, attributes and traceback locations remain available. This prevents a locals-dumping formatter from recovering arguments from those frames; it does not redact application exception messages, attributes, caller frames, or explicitly emitted logs.
Authentication keys are generated per server and passed to a new worker over its standard input; they are not embedded in the generated worker script. Authentication protects the listener from unrelated local users and accidental connections. It is not intended to isolate mutually untrusted processes running as the same operating-system user or as root.
Applications that need gevent inside the worker can pass a dictionary of
gevent.monkey.patch_all options as patch_gevent to worker_context.
The patch is applied on the worker main thread before the worker accepts its
first call.
If the parent process has monkey-patched threading with gevent, pass
gevent_friendly=True to both server_context and worker_context.
patch_gevent only controls patching inside the child; it does not select
the parent's transport. Starting the standard thread transport in a parent
with patched threading raises infi.blocking.GeventCompatibilityError
instead of running a blocking listener on the parent's gevent event loop.
This check also applies when gevent is patched after importing the library.
Worker-side patching remains supported with an unpatched parent.
In the gevent adapter, native background threads perform network I/O, while parent-side ACK and log handlers execute in greenlets on the server owner's hub. Internal background diagnostics use the same boundary. This keeps gevent-patched logging locks out of native RPC threads, including when one worker starts another. Readiness, shutdown RPC, and process-exit waits keep the owning hub responsive so it can deliver the worker's final log records. Worker callables still execute on the child main thread.
The gevent client serializes calls on each persistent connection using a greenlet-aware semaphore, including when the application has not patched threading. Waiting for that semaphore shares the call's I/O deadline; a waiting caller timing out does not close another caller's active connection. A cancelled calling greenlet does not release the connection until its native I/O task finishes.
Run the following commands:
easy_install -U infi.projector
projector devenv build
Python 3.11 and newer are supported.