Change:
I've had an SSH window open in the background and noticed that it keeps going through reconnection. Looking at the logs, it looks like vscode is often triggering reconnection, even though nothing strange is going on with my network, as far as I know. Noticed this at home and also the office network. This is the log from vscode. The SSH log doesn't show anything unusual before the resolver is invoked again. Has anything changed here lately?
Sorry this issue fell through the cracks. Are you still running into this?
Yes
Do you perhaps have a log with tracing enabled? The reason in the original log appears to be timeout. That is triggered here -- So the conditions are: a message was written to the socket 20 seconds ago and the server side didn't acknowledge it (and) no data was received from the server within the past 20 seconds (and) no previous timeout event was fired within the past 20 seconds (this just avoid sending many timeout events) (and) the renderer process appears responsive (Just speculating) I think we have fixed something in the terminal land and we now no longer send any data in an idle window. Could it be that your window becomes idle and the connection is dropped by SSH? (I believe due to some terminal heartbeat mechanism there was always data being written every 5 seconds, but now that is no longer happening).
Well, now I can't repro it.
I've more logging via . Please keep an eye out. In case you hit this again, the logging will have more data.
This issue has been closed automatically because it needs more information and has not had recent activity. See also our guidelines. Happy Coding!
Finally got it
It seems like the log message you touch didn't show up there. But, it does show up in an earlier reconnection in this window (before I enabled trace logging). So I'll just share the full logs This shows a window that was mostly idle with 2 reconnections, the second one had logging at the trace level enabled
Here's my interpretation: the management connection timed out at due to our own timeout logic. We wrote one message and that message didn't get acknowledged within 20s by the server. As an observation, the connection didn't receive any bytes from the server within 320s (5 minutes). this resulted in the core invoking on the SSH extension and the SSH extension replied with a new port i.e. instead of the previous . the extension host connection immediately closed at with code , indicating that perhaps the previous tunnel at was killed as part of invoking . Precisely 20 minutes later, at , both management and extension host connections receive a event from Chromium. I can't quite explain the first timeout, why would the server not acknowledge a message within 20 seconds? But the timing of the second disconnection seems to indicate to me that after 20 min of idleness, the underlying connection is closed. Anyone could be closing it: either on the client side by Chromium or the OS, either on the server side by nodejs or the OS, either by the SSH tunnel timing out. For the second disconnection I think we might need to do something to tackle . For a long time the terminal was doing a heartbeat mechanism which resulted in data being sent over the wire (and that would not make the connection idle), but that was fixed via Right now, if you are really idle in a window, the underlying connection will be idle too and I think the OS or someone closes it as idle after 20 minutes.
My best guess is some other weird optimization where network requests don't even get delivered when an app is in the background. I've noticed this in windows that are not focused
This issue has been closed automatically because it needs more information and has not had recent activity. See also our guidelines. Happy Coding!

Discussion:
export type SocketCloseEvent = NodeSocketCloseEvent | WebSocketCloseEvent | undefined; <ins> export interface SocketTimeoutEvent { readonly unacknowledgedMsgCount: number; readonly timeSinceOldestUnacknowledgedMsg: number; readonly timeSinceLastReceivedSomeData: number; } </ins> export interface ISocket extends IDisposable { onData(listener: (e: VSBuffer) => void): IDisposable; onClose(listener: (e: SocketCloseEvent) => void): IDisposable;

this._last = null; } <ins> public length(): number { let result = 0; let current = this._first; while (current) { current = current.next; result++; } return result; } </ins> public peek(): T | null { if (!this._first) { return null;

private readonly _onSocketClose = new BufferedEmitter<SocketCloseEvent>(); readonly onSocketClose: Event<SocketCloseEvent> = this._onSocketClose.event; <del> private readonly _onSocketTimeout = new BufferedEmitter<void>(); readonly onSocketTimeout: Event<void> = this._onSocketTimeout.event; </del> <ins> private readonly _onSocketTimeout = new BufferedEmitter<SocketTimeoutEvent>(); readonly onSocketTimeout: Event<SocketTimeoutEvent> = this._onSocketTimeout.event; </ins> public get unacknowledgedCount(): number { return this._outgoingMsgId - this._outgoingAckId;

if (!this._loadEstimator.hasHighLoad()) { // Trash the socket this._lastSocketTimeoutTime = Date.now(); <del> this._onSocketTimeout.fire(undefined); </del> <ins> this._onSocketTimeout.fire({ unacknowledgedMsgCount: this._outgoingUnackMsg.length(), timeSinceOldestUnacknowledgedMsg, timeSinceLastReceivedSomeData }); </ins> return; } }

} this._beginReconnecting(); })); <del> this._register(protocol.onSocketTimeout(() => { </del> <ins> this._register(protocol.onSocketTimeout((e) => { </ins> const logPrefix = commonLogPrefix(this._connectionType, this.reconnectionToken, true); <del> this._options.logService.info(`${logPrefix} received socket timeout event.`); </del> <ins> this._options.logService.info(`${logPrefix} received socket timeout event (unacknowledgedMsgCount: ${e.unacknowledgedMsgCount}, timeSinceOldestUnacknowledgedMsg: ${e.timeSinceOldestUnacknowledgedMsg}, timeSinceLastReceivedSomeData: ${e.timeSinceLastReceivedSomeData}).`); </ins> this._beginReconnecting(); }));