Skip to main content
Use an additional subprocess when two processes need the same live environment. For example, a primary process can wait for a result file while a child receives input and writes that file. Both processes share the operation’s filesystem and resource limits. Use the REST subprocess endpoints for this workflow. Starting a new operation creates a separate runtime; the Python SDK’s popen() wrapper also starts its own operation. Complete access setup before using the REST endpoints. The complete interactive-process recipe uses one bounded standard-library Python program.

Keep the parent alive until the work is done

The primary process controls the operation lifetime. When it finishes, finalization begins and additional subprocesses cannot continue independently. Design the parent with a bounded coordination condition, such as waiting for a completion file until a deadline. A subprocess finishing does not finalize the parent or create its own result image. Before spawning a child, confirm that the parent has reached ASSIGNED or EXECUTING and has published an application readiness signal. Status alone says that the runtime is active; it does not prove that a service or file inside the runtime is ready. A short GET /operations/{operationId}?inflight=1 poll can inspect partial parent output when a dedicated readiness endpoint is unavailable. Client arrows represent REST requests, not direct connections to guest processes. This is the normal path in the interactive recipe. The file coordinates the two processes. If the primary process ends first, finalization stops any remaining child; the client cannot keep it alive by continuing to poll.

Spawn and address the child

Send an ExecSpec to POST /operations/{operationId}/subprocesses. VM-level fields such as image, disposable, timeout, and resources_limits belong to the parent operation and are not accepted in the child request. A successful response returns a fresh spid of 2 or greater and a Location for its result. Preserve both the parent operation UUID and the child spid. If the create request times out, inspect the event stream for a matching spawn event before retrying because the child may already exist. See Spawn an additional subprocess.

Send ordered input and EOF

Set the child’s initial stdin.close to false when later writes are required. Send each chunk to POST /operations/{operationId}/subprocesses/{spid}/stdin. Serialize writes to the same child when order matters; concurrent writes have unspecified order. The API does not append a newline. Use encoding: "ascii" for text and encoding: "base64" for arbitrary bytes. Send close: true on the final write, or send an empty close-only request, to deliver EOF. A 204 confirms the request completed. A 504 leaves delivery uncertain, so a blind retry can duplicate input. Add sequence numbers or another application-level idempotency marker when duplicate input would be harmful. See Write to subprocess stdin.

Observe completion or signal the process

Read GET /operations/{operationId}/subprocesses/{spid} until the child result is ready. Honor Retry-After for a 425 response and keep polling bounded. Check the child’s exit code, signal, timeout flag, stdout, stderr, encoding, and truncation separately from the parent result. To stop a live child, call DELETE /operations/{operationId}/subprocesses/{spid}?signal=SIGTERM or choose another documented signal. The signal targets the subprocess’s process group. Completion is observed later in the child result: a signalled child reports exit_code: -1 and the signal number. Signalling spid=1 ends the primary workload and therefore ends the operation. See Signal a subprocess.

Handle lifetime races

The interactive-process recipe covers normal two-write input with EOF, a child terminated by SIGTERM while the parent completes normally, and a negative case where the parent finishes first. Its finally block cancels any parent operation left active after a client-side failure.