]> asedeno.scripts.mit.edu Git - PuTTY.git/blobdiff - windows/winhsock.c
Implement deferred closing of Windows handle-sockets.
[PuTTY.git] / windows / winhsock.c
index 7fe02f634d789aad52491cd7b50c7899b1fc5fee..8acb82be61b5493195c26e1600d03b62878a295e 100644 (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;
 }