Download: Stable · Snapshot | Docs | Changes | Wishlist
A couple of users have reported that on a Windows 11 laptop, if PuTTY is running when the laptop is suspended, then after the system resumes, the PuTTY window might no longer update its terminal window. Keystrokes typed into the window will still be sent to the server and have their usual effects, but data returned from the server won't be displayed in the window.
One of the users who reported this provided a helpful analysis of
the problem (thank you!). According to their analysis, the problem
starts with GUI PuTTY's use of the
SetTimer Windows API
function to request a
WM_TIMER window message. This is
used throughout PuTTY to manage scheduled future events, including
display updates (which it rate-limits).
WM_TIMER message was due to arrive while the
system was suspended, it will simply never be delivered. As a result,
the code that would have responded to that by scheduling further
timers gets into a confused state.
An obvious response would be to detect that the system has been
suspended, and use that to reboot PuTTY's timer subsystem on purpose.
Windows has a message
WM_POWERBROADCAST which is intended
to notify applications of changes to the power situation, including
resume from suspend – but our user reports that Windows 11 has
introduced a new type of suspension known as “Modern Standby” which
does not send
WM_POWERBROADCAST, or (as far as we know)
any replacement message.
This issue is likely to affect other timed events in PuTTY as well as display updates. For example, SSH repeat key exchange may be affected too. Display updates are just the most obvious effect, and the one that shows up first.
This issue is listed as Taxing difficulty because as far as I know the PuTTY team currently doesn't have access to a Windows 11 machine of a type that exhibits this problem. (Apparently not even all Win11 devices can do Modern Standby.) So it's difficult for us to test a candidate fix, or even a candidate workaround.
Our helpful user suggested a workaround strategy that involves checking for a missed timer when any call to the timing subsystem occurs, and resetting the timing subsystem. This would arrange, for example, that the next keypress would be likely to unblock the display updates. However, we're unable to test this strategy. Also, it relies on the user noticing the problem and prodding the window, which might not be good enough if a security-relevant timer also went missing (e.g. for an SSH rekey).
Other possibilities that have occurred to me, which I also can't test easily:
WM_TIMER. For example, perhaps we could do our own timing by having a separate thread whose job is to do a timed
WaitForSingleObjectsleep on an event object; respond to a timeout by posting a message back to the main thread; and respond to the event object by changing its timeout value and resuming its sleep. But I don't know whether Modern Standby would handle that unhelpfully either: what does happen if you're in the middle of a timed wait and the system goes to sleep?