1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-25 01:02:24 +00:00

Implement deferred closing of Windows handle-sockets.

When a handle socket is in THAWING state and handle_socket_unfreeze is
gradually passing the backlogged data on to the plug, the plug might
suddenly turn round and close the socket in the course of handling
plug_receive(), which means that handle_socket_unfreeze had better be
careful not to have had everything vanish out from under it when that
call returns. To solve this, I've added a 'deferred close' flag which
handle_socket_unfreeze can set around its call to plug_receive, and
handle_socket_close will detect that and not actually free the socket,
instead leaving that for handle_socket_unfreeze to do under its own
control.
This commit is contained in:
Simon Tatham 2017-02-16 20:26:58 +00:00
parent 8d48caa849
commit 92d855d0fe

View File

@ -42,6 +42,8 @@ struct Socket_handle_tag {
/* Data received from stderr_H, if we have one. */
bufchain stderrdata;
int defer_close, deferred_close; /* in case of re-entrance */
char *error;
Plug plug;
@ -109,6 +111,11 @@ static void sk_handle_close(Socket s)
{
Handle_Socket ps = (Handle_Socket) s;
if (ps->defer_close) {
ps->deferred_close = TRUE;
return;
}
handle_free(ps->send_h);
handle_free(ps->recv_h);
CloseHandle(ps->send_H);
@ -169,10 +176,17 @@ static void handle_socket_unfreeze(void *psv)
assert(len > 0);
/*
* Hand it off to the plug.
* Hand it off to the plug. Be careful of re-entrance - that might
* have the effect of trying to close this socket.
*/
ps->defer_close = TRUE;
new_backlog = plug_receive(ps->plug, 0, data, len);
bufchain_consume(&ps->inputdata, len);
ps->defer_close = FALSE;
if (ps->deferred_close) {
sk_handle_close(ps);
return;
}
if (bufchain_size(&ps->inputdata) > 0) {
/*
@ -310,5 +324,7 @@ Socket make_handle_socket(HANDLE send_H, HANDLE recv_H, HANDLE stderr_H,
ret->stderr_h = handle_input_new(ret->stderr_H, handle_stderr,
ret, flags);
ret->defer_close = ret->deferred_close = FALSE;
return (Socket) ret;
}