Skip to main content

Module nonwaiting_write

Module nonwaiting_write 

Source
Expand description

Diagnostic writes that never wait for the reader of a descriptor.

While --max-log-bytes is in force, termination of a run must not depend on any diagnostic write (review of https://github.com/rrnewton/hermit/pull/3686). A plain write(2) to a blocking stderr whose reader stopped reading waits forever, so every hermit diagnostic that can run in a capped run before the cap or the 123 classification goes through write_without_waiting once forbid_waiting_diagnostics has been called.

crate::util::RetryingStderr reads the same flag: while it is set, its writes go through write_without_waiting_for_a_reader and wait only within its bounded deadline, never inside write(2).

This lives in detcore, below the hermit library and binary, because detcore’s own stderr writer reads the flag, and because hermit’s proc_mount writes its warning from the namespace-only pre_exec callback, after fork, and from the container init: every function here except write_without_waiting_for_a_reader makes only syscalls and signal-set operations, without allocation, stdio locks or formatting.

Functions§

diagnostics_must_not_wait
Whether forbid_waiting_diagnostics was called. A single atomic load, so it is safe after fork and in a signal handler.
forbid_waiting_diagnostics
From now on, in this process and every process it forks, a diagnostic that asks diagnostics_must_not_wait is written once with write_without_waiting and omitted when stderr cannot take it at once, and crate::util::RetryingStderr never waits inside write(2). Only hermit’s main calls this, when --max-log-bytes is given.
last_errno
The calling thread’s errno, 0 when there is none.
proc_self_fd_path
/proc/self/fd/<fd> as a NUL-terminated path, built without allocating: the crossing writer may run with arbitrary locks held.
suppressing_diagnostic_signals
Run one diagnostic write (write returns its errno, 0 for none) so that no signal it generates escapes.
write_without_waiting
Put bytes on fd once, without waiting for the other end and without letting the attempt raise a signal. A diagnostic that cannot be delivered that way is omitted: the exit status still says why the run ended.
write_without_waiting_for_a_reader
One write of bytes to fd that cannot wait for a reader to drain the file, for a writer that then waits itself, within its own bound, when it is told the file is full (crate::util::RetryingStderr while diagnostics_must_not_wait). Returns the bytes written, which may be fewer than bytes.len(), or the error; WouldBlock means full.