wolfssh/apps
John Safranek 93f390092b Never wait on the child in the shell loop
SHELL_Subsystem() is the only reader of the child's output, so it must never be
the thing the child is waiting for. It was: the pass that writes the peer's
input to the child's stdin ran ahead of the pass that reads its stdout, and on
a pass with buffered channel data the output descriptors were left out of the
select() altogether. A child that fills its stdout pipe stops reading stdin,
the write blocks, and nothing is left to empty the pipe that would release it.
sshd_stdin_eof_test.sh case 2 is the shape that reaches it: a half-close with
the send window full leaves the whole window buffered, and the burst that
follows is up to four 32K writes with no read in between.

- The child's output is watched on every pass. A pass with work already in
  hand polls with a zero timeout instead of skipping select(), so it still
  sees the child's output.
- The descriptor written to is non-blocking, and what a short write leaves is
  carried in channelBuffer to the next pass, which waits for the child in
  select() rather than inside write(). Only EAGAIN keeps the remainder; any
  other short write still ends the session.
- The child's stdin closes on the peer's EOF once that remainder is gone too,
  not just once the channel is drained.
- A channel retired under us drops the remainder with the descriptor.
2026-08-31 11:53:29 -05:00
..
wolfssh Handle the EOF status in apps and examples 2026-08-31 11:53:29 -05:00
wolfsshd Never wait on the child in the shell loop 2026-08-31 11:53:29 -05:00
include.am
wolfssh-options.c wolfsshd: let QNX own the host key's permissions 2026-08-25 14:33:52 -06:00