mirror of https://github.com/wolfSSL/wolfssh.git
Report the disconnect with no channel to drop
wolfSSH_shutdown() set ssh->error to WS_DISCONNECT only inside the channel branch, so a flush that emptied the buffer with the channel already retired left behind the WS_WANT_WRITE that queued it. echoserver and sftpclient read that error and burn ten wolfSSH_worker() calls on a write that is already done. TestShutdownFlushesWithNoChannel asserts it. Issue: F-8837pull/1192/head
parent
a7fda8f6a3
commit
d05978f00d
11
src/ssh.c
11
src/ssh.c
|
|
@ -1161,13 +1161,16 @@ int wolfSSH_shutdown(WOLFSSH* ssh)
|
|||
* and the wait for a close that will not come. RFC 4253 section 11.1. */
|
||||
if (channel != NULL && ssh->disconnected) {
|
||||
WLOG(WS_LOG_DEBUG, "Session already disconnected, nothing to send");
|
||||
/* An unfinished flush owns ssh->error. Callers gate their retry on
|
||||
* WS_WANT_WRITE, so overwriting it strands the queued disconnect. */
|
||||
if (flushRet == WS_SUCCESS)
|
||||
ssh->error = WS_DISCONNECT;
|
||||
channel = NULL;
|
||||
}
|
||||
|
||||
/* Report the dead session with or without a channel to drop: callers
|
||||
* gate their retry on ssh->error, and the flush above may have just
|
||||
* emptied the output buffer they would be retrying for. An unfinished
|
||||
* flush owns the error instead, since that retry is still owed. */
|
||||
if (ssh != NULL && ssh->disconnected && flushRet == WS_SUCCESS)
|
||||
ssh->error = WS_DISCONNECT;
|
||||
|
||||
/* if channel close was not already sent then send it */
|
||||
if (channel != NULL && !channel->closeTxd) {
|
||||
if (ret == WS_SUCCESS) {
|
||||
|
|
|
|||
|
|
@ -3583,6 +3583,9 @@ static void TestShutdownFlushesWithNoChannel(void)
|
|||
AssertIntEQ(ret, WS_CHANNEL_CLOSED);
|
||||
AssertFalse(wolfSSH_OutputPending(ssh));
|
||||
AssertIntEQ(out[LENGTH_SZ + 1], MSGID_DISCONNECT);
|
||||
/* The flush finished, so the WS_WANT_WRITE that queued it is stale.
|
||||
* Leaving it sends the caller back for a write that is already done. */
|
||||
AssertIntEQ(wolfSSH_get_error(ssh), WS_DISCONNECT);
|
||||
|
||||
wolfSSH_free(ssh);
|
||||
wolfSSH_CTX_free(ctx);
|
||||
|
|
|
|||
Loading…
Reference in New Issue