-
-
Notifications
You must be signed in to change notification settings - Fork 152
Description
I have a relatively new laptop with Windows 11 (that's important because this combination can use Modern Standby in Windows).
When setting the laptop to sleep and waking it up, existing KiTTY windows stop displaying any changes, although the connection works and commands on the server are executed (I just can't see that).
Doing full screen refresh, such as bringing the window out of focus and back, using scrolling and so on, reveals the changed content, but normal keypress and/or mouse activity does not.
After waiting a few minutes, terminal operation usually comes to normal, so the hard patience here can be a workaround :)
I've investigated this bug and found that this problem is in Putty code (so I'll be cross-posting this to Putty authors too). Putty does not restore connections, but if the connection is not dropped at all during the sleep, Putty gets the symptoms described above.
- Windows delays
WM_TIMERmessages that were scheduled to arrive during the time the computer went to sleep for the period of sleep. However,GetTickCount()continues to advance when that sleep mode is actually Modern StandBy. - That message (of
TIMING_TIMER_ID) was supposed to invoke therun_timers()function that pops and executes the callbacks at the front oftimerspriority queue (whose execution time has come). - Most of the time, the front of
timersis an event scheduled approximately 2 minutes ahead. - Now the computer wakes up and we have the front element of
timerspointing to the past (in terms ofGetTickCount()), but respectiveWM_TIMERwill arrive in another one or two minutes. - Because of that,
schedule_timer()would normally not calltimer_change_notify()that schedules the newWM_TIMERmessage, so no one would callrun_timers()and execute what we've just scheduled. - Now, look at
term_update_callback()that is actually responsible for the terminal window update. There's a protection against its repetitive calling that setsterm->window_update_cooldownand schedules its reset after 20ms usingschedule_timer(). - Whoosh!
window_update_cooldownwas set, but theschedule_timer()does not work any more, so cooldown is not reset back, andterm_update_callback()does not work.
To solve the problem for me, I first tried to reschedule the WM_TIMER message from WM_POWERBROADCAST. Surprise! Windows does not send WM_POWERBROADCAST when it enters or leaves Modern Standby. Nothing can be done here.
So my solution is to look at the front element of timers. Should its due time be too much (like 10 seconds) in the past, we can generally think that something bad has happened with timers and reschedule WM_TIMER .
--- orig\timing.c 2023-03-06 21:40:49 +0300
+++ KiTTY-0.76.1.5\0.76b_My_PuTTY\timing.c 2023-03-27 05:49:49 +0300
@@ -137,10 +137,12 @@
}
first = (struct timer *)index234(timers, 0);
- if (first == t) {
+ if (first == t || first != NULL && first->now + 10 * (TICKSPERSEC) < now) {
/*
* This timer is the very first on the list, so we must
* notify the front end.
+ * Also notify if the first timer has seriously missed its run time,
+ * most likely due to a system sleep event.
*/
timer_change_notify(first->now);
}