Expand description
Messages between services: sending one, receiving one, and what the failures mean.
§The model in four sentences
A service owns one endpoint with a bounded queue (16 messages, CLAUDE.md 8.5). A send COPIES the
bytes into the receiver’s queue and returns; it does not wait for the receiver to look at them. So
a successful send means queued, not processed - if you need to know it was acted on, the
protocol has to say so, which is what crate::call is for. And a message can carry a
capability, which MOVES: the sender no longer holds it afterwards.
§Why every failure here is worth reading rather than retrying
The three you will actually meet say different things and want different answers:
Error::Unreachable- the peer died, or its name does not resolve right now. Nothing happened. The name is stable even though the instance is not (CLAUDE.md invariant 11), so the answer iscap::reacquireand then retry - not a sleep.Error::Busy- the peer is alive and its queue is full. Nothing happened. Congestion is transient; pace and retry, and do not go looking for a peer that never went away.Error::InvalidInput- the message exceeds one page. Nothing will make that work; send less.
A fourth appears only when you hand a capability away with send_granting:
Error::PermissionDenied- the capability you tried to send does not carryGRANT. Nothing moved, so it is still yours and the slot is still yours to reclaim. This is the first of the three checks CLAUDE.md 8.5 asks of every transfer, and it is the one a compiler cannot make for you.
§The deadlock rule, which the kernel will not save you from
If A and B both send to each other, at least one direction MUST use try_send. A blocking send
into a full queue waits, and two services waiting on each other wait forever. The kernel does not
detect this and does not break it (CLAUDE.md 8.9) - the supervisor’s starvation watchdog is a last
resort, not a design.
Modules§
- exact
- The kernel’s exact refusal, for the few programs whose job is to tell refusals apart.
Structs§
- Message
- An IPC message as seen by service code.
Constants§
- MAX_
BYTES - The largest message body, in bytes: one page (CLAUDE.md 8.5).
Functions§
- park
- Sleep forever, having nothing left to do.
- peer
- A capability to a peer this service was wired to at spawn, by name.
- peer_at
- A capability to a peer this service was WIRED TO at spawn, by position.
- recv
- Block until a message arrives on this service’s endpoint.
- recv_
within - Block for a message, giving up after
secs. - recv_
within_ ms recv_within, bounded in MILLISECONDS.- reply
- Answer a request on the reply capability its client sent, then give that capability back.
- send
- Send to a service by NAME, blocking if its queue is full.
- send_
granting - Send a message that CARRIES a capability, giving it away.
- send_to
- Send through a capability you already hold, rather than resolving a name.
- take_
sent_ cap - The capability that arrived embedded in the message just received, if any.
- try_
recv - Take a message if one is already waiting, without blocking.
- try_
send - Send to a service by NAME, refusing rather than waiting if its queue is full.
- try_
send_ to - Non-blocking
send_to.