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:
parent
8d48caa849
commit
92d855d0fe
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user