mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-02-09 16:36:34 +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. */
|
/* Data received from stderr_H, if we have one. */
|
||||||
bufchain stderrdata;
|
bufchain stderrdata;
|
||||||
|
|
||||||
|
int defer_close, deferred_close; /* in case of re-entrance */
|
||||||
|
|
||||||
char *error;
|
char *error;
|
||||||
|
|
||||||
Plug plug;
|
Plug plug;
|
||||||
@ -109,6 +111,11 @@ static void sk_handle_close(Socket s)
|
|||||||
{
|
{
|
||||||
Handle_Socket ps = (Handle_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->send_h);
|
||||||
handle_free(ps->recv_h);
|
handle_free(ps->recv_h);
|
||||||
CloseHandle(ps->send_H);
|
CloseHandle(ps->send_H);
|
||||||
@ -169,10 +176,17 @@ static void handle_socket_unfreeze(void *psv)
|
|||||||
assert(len > 0);
|
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);
|
new_backlog = plug_receive(ps->plug, 0, data, len);
|
||||||
bufchain_consume(&ps->inputdata, 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) {
|
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->stderr_h = handle_input_new(ret->stderr_H, handle_stderr,
|
||||||
ret, flags);
|
ret, flags);
|
||||||
|
|
||||||
|
ret->defer_close = ret->deferred_close = FALSE;
|
||||||
|
|
||||||
return (Socket) ret;
|
return (Socket) ret;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user