ipc
-std.ipc — child-to-parent back-channel IPC.
+std.ipc — child-to-parent and two-way channel IPC with descriptor passing.
import std.ipc
parent_channel_raw extern
parent_channel_raw() -> int
- Returns the parent-channel fd if the parent spawned this process via os.run_pipe (i.e. AETHER_IPC_FD is set in env and the named fd is open); -1 otherwise. Children of os.run / os.run_capture see -1 — those don't open a back-channel. On Windows always -1 (v1 stub). The fd value is whatever the parent picked; current parent-side default is 3 but consumers MUST NOT hardcode that.
+parent_channel_kind_raw extern
+parent_channel_kind_raw() -> string
+ write_raw extern
+write_raw(fd, bytes) -> string
+ fd: int, bytes: string
+read_raw extern
+read_raw(fd, max) -> (string, string)
+ fd: int, max: int
+send_fd_raw extern
+send_fd_raw(ch, fd, payload) -> string
+ ch: int, fd: int, payload: string
+recv_fd_raw extern
+recv_fd_raw(ch, max) -> (int, string, string)
+ ch: int, max: int
+set_sock_buf_raw extern
+set_sock_buf_raw(fd, size) -> int
+ fd: int, size: int
+get_cloexec_raw extern
+get_cloexec_raw(fd) -> int
+ fd: int
+test_ipc_send_two_fds extern
+test_ipc_send_two_fds(ch, fd1, fd2, payload) -> int
+ ch: int, fd1: int, fd2: int, payload: string
+test_send_async_raw extern
+test_send_async_raw(fd, payload) -> int
+ fd: int, payload: string
parent_channel fn
parent_channel() -> int
- Aether-side wrappers. parent_channel returns the raw int from the extern; -1 sentinel for "no parent channel."
+Returns the parent-channel fd if the parent spawned this process via os.run_pipe or os.run_socket (i.e. AETHER_IPC_FD is set in env and the named fd is open); -1 otherwise.
+parent_channel_kind fn
+parent_channel_kind() -> string
+ Returns the channel kind: "pipe" for a pipe channel, "socket" for a socket channel, or "" when no channel exists.
write fn
write(fd, bytes) -> string
fd: int, bytes: string
-Write `bytes` to the back-channel `fd`. Returns "" on success, non-empty error string on failure. Wraps std.net.fd_write — the underlying transport is an inherited pipe, so the same byte-stream semantics apply (partial writes are possible on interrupted system calls; the wrapped C extern handles EINTR). For the common case where the child writes one payload and exits, prefer write_close so the parent's read_all loop sees EOF promptly.
+Write `bytes` to `fd`. Returns "" on success, non-empty error string on failure. Loops on short writes and handles SIGPIPE / EINTR.
write_close fn
write_close(fd, bytes) -> string
fd: int, bytes: string
-Write `bytes` then close the channel. The common case: child produces one structured report at exit and closes the fd so the parent's drain loop sees EOF and stops. Calling close releases the writer's reference on the pipe; the parent sees EOF only after every writer has closed. If the child is itself going to exit immediately after, the kernel will close the fd anyway during process teardown — explicit close is still preferred because it lets the parent's reader unblock before the child exits, useful when the parent's reader runs in the same thread as the child-wait loop.
+Write `bytes` then close the channel.
+read fn
+read(ch, max) -> (string, string)
+ ch: int, max: int
+Binary-safe read of up to `max` bytes from `fd`. Returns (payload, err). On EOF (end-of-stream), returns ("", ""). On error, returns ("", err).
+send_fd fn
+send_fd(ch, fd, payload) -> string
+ ch: int, fd: int, payload: string
+Send one open file descriptor `fd` across socket channel `ch`, accompanied by `payload` (must be at least 1 byte). Returns "" on success, error message on failure.
+recv_fd fn
+recv_fd(ch, max) -> (int, string, string)
+ ch: int, max: int
+Receive one open file descriptor and payload up to `max` bytes from socket channel `ch`. Returns (received_fd, payload, err).