simon-git: putty (main): Simon Tatham
Commits to Tartarus hosted VCS
tartarus-commits at lists.tartarus.org
Thu Sep 30 19:22:50 BST 2021
TL;DR:
15419745 Windows dputs: use WriteFile to avoid stdio buffering.
dde65900 handle_write_eof: delegate CloseHandle back to the client.
6dfe941a Windows Pageant: fix hang due to queued callbacks.
e7dd2421 Pageant: actually link requests on to their queues.
Repository: https://git.tartarus.org/simon/putty.git
On the web: https://git.tartarus.org/?p=simon/putty.git
Branch updated: main
Committer: Simon Tatham <anakin at pobox.com>
Date: 2021-09-30 19:22:50
commit 1541974564a65b6edbf09447e8cf54355fe10805
web diff https://git.tartarus.org/?p=simon/putty.git;a=commitdiff;h=1541974564a65b6edbf09447e8cf54355fe10805;hp=a73aaf945728a15159a274193c6505a04111d2f8
Author: Simon Tatham <anakin at pobox.com>
Date: Thu Sep 30 18:33:16 2021 +0100
Windows dputs: use WriteFile to avoid stdio buffering.
Trying to debug a problem involving threads just now, it turned out
that the version of the diagnostics going to my debug.log was getting
data in a different order from the version going to the debug console.
Now I open and write to debug_fp by going directly to the Win32 API
instead of via a buffering userland stdio, and that seems to have
solved the problem.
windows/utils/dputs.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
commit dde659004083b575547f2740aaa56fdf64523770
web diff https://git.tartarus.org/?p=simon/putty.git;a=commitdiff;h=dde659004083b575547f2740aaa56fdf64523770;hp=1541974564a65b6edbf09447e8cf54355fe10805
Author: Simon Tatham <anakin at pobox.com>
Date: Thu Sep 30 19:16:20 2021 +0100
handle_write_eof: delegate CloseHandle back to the client.
When a writable HANDLE is managed by the handle-io.c system, you ask
to send EOF on the handle by calling handle_write_eof. That waits
until all buffered data has been written, and then sends an EOF event
by simply closing the handle.
That is, of course, the only way to send an EOF signal on a handle at
all. And yet, it's a bug, because the handle_output system does not
take ownership of the handle you give it: the client of handle_output
retains ownership, keeps its own copy of the handle, and will expect
to close it itself.
In most cases, the extra close will harmlessly fail, and return
ERROR_INVALID_HANDLE (which the caller didn't notice anyway). But if
you're unlucky, in conditions of frantic handle opening and closing
(e.g. with a lot of separate named-pipe-style agent forwarding
connections being constantly set up and torn down), the handle value
might have been reused between the two closes, so that the second
CloseHandle closes an unrelated handle belonging to some other part of
the program.
We can't fix this by giving handle_output permanent ownership of the
handle, because it really _is_ necessary for copies of it to survive
elsewhere: in particular, for a bidirectional file such as a serial
port or named pipe, the reading side also needs a copy of the same
handle! And yet, we can't replace the handle_write_eof call in the
client with a direct CloseHandle, because that won't wait until
buffered output has been drained.
The solution is that the client still calls handle_write_eof to
register that it _wants_ an EOF sent; the handle_output system will
wait until it's ready, but then, instead of calling CloseHandle, it
will ask its _client_ to close the handle, by calling the provided
'sentdata' callback with the new 'close' flag set to true. And then
the client can not only close the handle, but do whatever else it
needs to do to record that that has been done.
windows/conpty.c | 3 ++-
windows/handle-io.c | 8 +++++---
windows/handle-socket.c | 16 +++++++++++++---
windows/platform.h | 2 +-
windows/plink.c | 8 +++++++-
windows/serial.c | 3 ++-
6 files changed, 30 insertions(+), 10 deletions(-)
commit 6dfe941a7309a5af2088061ab0a745555f31b879
web diff https://git.tartarus.org/?p=simon/putty.git;a=commitdiff;h=6dfe941a7309a5af2088061ab0a745555f31b879;hp=dde659004083b575547f2740aaa56fdf64523770
Author: Simon Tatham <anakin at pobox.com>
Date: Thu Sep 30 18:31:39 2021 +0100
Windows Pageant: fix hang due to queued callbacks.
In the Windows Pageant message loop, we were alternating between
MsgWaitForMultipleObjects with timeout=INFINITE, and
run_toplevel_callbacks. But run_toplevel_callbacks doesn't loop until
the callback queue is empty: it just runs at least one of the
currently queued callbacks, so that some progress was made. So if two
or more callbacks were queued, we'd leave the rest in the queue and go
back into MsgWaitForMultipleObjects, which could hang indefinitely.
(A very silly workaround was available: move the mouse over the
Pageant systray icon! Every mouse event would terminate the wait and
let you get one more iteration of run_toplevel_callbacks.)
Now we do the same thing as in other main loops: if any further
callbacks are pending, then we still run MsgWaitForMultipleObjects,
but we do it with timeout=0 instead of timeout=INFINITE, so that we
won't go back to a _blocking_ sleep until all callbacks have been
serviced.
windows/pageant.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
commit e7dd2421cfaf6dd75b316c011e4b10843d2007a6
web diff https://git.tartarus.org/?p=simon/putty.git;a=commitdiff;h=e7dd2421cfaf6dd75b316c011e4b10843d2007a6;hp=6dfe941a7309a5af2088061ab0a745555f31b879
Author: Simon Tatham <anakin at pobox.com>
Date: Thu Sep 30 18:56:26 2021 +0100
Pageant: actually link requests on to their queues.
When I create any class that implements PageantAsyncOp, I had intended
to link its pao.cr list node on to the list in the appropriate
PageantClientInfo, so that if that PageantClientInfo was destroyed
prematurely (e.g. an agent connection was abruptly closed), we could
destroy all the pending requests containing a pointer to it.
I did this linking by setting the linked-list fields in pao.cr to
point to the appropriate places in the existing list - but I didn't
modify the pointer fields _in_ the existing list to point to the new
operation at all. So nothing ever actually got linked on to any of
those queues!
pageant.c | 2 ++
1 file changed, 2 insertions(+)
More information about the tartarus-commits
mailing list