Errors, Ordering, Slow Consumers, and Shutdown
Context follows instructions
Channel payloads include an ErrorContext. Each owner adds its own operation
context before handling the message. Failures can therefore report the path
through input, routing, Screen, PTY, or plugin code rather than only the final
I/O error.
Errors are deliberately classified by call site. Structural owner-thread failure can be fatal; expected pane or OS-operation failures are often logged as non-fatal so the rest of the session remains usable.
Logical completion prevents action races
Some actions cross several threads before their effect is safe to follow.
NotificationEnd travels with the instruction and resolves a oneshot when its
owning path ends. The route thread normally caps the wait at one second; select
CLI operations may wait indefinitely because their API promises a completed
result.
Slow PTY output meets bounded admission
Terminal reader tasks send bytes through a capacity-50 channel to Screen. A backed-up Screen eventually slows readers instead of allowing unbounded output messages. Rendering is separately debounced, so parsing progress does not require repainting after every chunk.
Slow PTY input is isolated
The writer preserves partial writes with an offset and retries them. A stuck terminal does not block other terminal queues. At 10 MiB pending for one pane, Zellij logs and clears that queue: explicit degradation is preferable to unlimited session memory.
Shutdown follows ownership
SessionMetaData::drop sends Exit to PTY, Screen, plugin, writer, and
background-job owners, then joins each thread. The PTY owner’s own Drop
closes remaining children. Terminal-reader sends that fail during teardown are
intentionally ignored at EOF because the consumer may already be gone.
This is a practical lesson: a closed channel during coordinated shutdown is a lifecycle signal, not automatically an application bug.