mirror of https://github.com/wolfSSL/wolfssh.git
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. |
||
|---|---|---|
| .. | ||
| wolfssh | ||
| wolfsshd | ||
| include.am | ||
| wolfssh-options.c | ||