]> asedeno.scripts.mit.edu Git - PuTTY.git/blobdiff - windows/winhandl.c
Key rollover: rewrite the PGP keys manual appendix.
[PuTTY.git] / windows / winhandl.c
index 6b129ad886591c4fb9d5dd73c9935ede24089b9f..7c282fc7d5502f128f300d3ea09d942026d4c525 100644 (file)
@@ -115,7 +115,7 @@ static DWORD WINAPI handle_input_threadfunc(void *param)
     struct handle_input *ctx = (struct handle_input *) param;
     OVERLAPPED ovl, *povl;
     HANDLE oev;
-    int readret, readlen;
+    int readret, readlen, finished;
 
     if (ctx->flags & HANDLE_FLAG_OVERLAPPED) {
        povl = &ovl;
@@ -165,15 +165,31 @@ static DWORD WINAPI handle_input_threadfunc(void *param)
            (ctx->flags & HANDLE_FLAG_IGNOREEOF))
            continue;
 
+        /*
+         * If we just set ctx->len to 0, that means the read operation
+         * has returned end-of-file. Telling that to the main thread
+         * will cause it to set its 'defunct' flag and dispose of the
+         * handle structure at the next opportunity, in which case we
+         * mustn't touch ctx at all after the SetEvent. (Hence we do
+         * even _this_ check before the SetEvent.)
+         */
+        finished = (ctx->len == 0);
+
        SetEvent(ctx->ev_to_main);
 
-       if (!ctx->len)
+       if (finished)
            break;
 
        WaitForSingleObject(ctx->ev_from_main, INFINITE);
        if (ctx->done) {
+            /*
+             * The main thread has asked us to shut down. Send back an
+             * event indicating that we've done so. Hereafter we must
+             * not touch ctx at all, because the main thread might
+             * have freed it.
+             */
             SetEvent(ctx->ev_to_main);
-           break;                     /* main thread told us to shut down */
+            break;
         }
     }
 
@@ -280,6 +296,12 @@ static DWORD WINAPI handle_output_threadfunc(void *param)
     while (1) {
        WaitForSingleObject(ctx->ev_from_main, INFINITE);
        if (ctx->done) {
+            /*
+             * The main thread has asked us to shut down. Send back an
+             * event indicating that we've done so. Hereafter we must
+             * not touch ctx at all, because the main thread might
+             * have freed it.
+             */
            SetEvent(ctx->ev_to_main);
            break;
        }
@@ -304,8 +326,16 @@ static DWORD WINAPI handle_output_threadfunc(void *param)
        }
 
        SetEvent(ctx->ev_to_main);
-       if (!writeret)
+       if (!writeret) {
+            /*
+             * The write operation has suffered an error. Telling that
+             * to the main thread will cause it to set its 'defunct'
+             * flag and dispose of the handle structure at the next
+             * opportunity, so we must not touch ctx at all after
+             * this.
+             */
            break;
+        }
     }
 
     if (povl)
@@ -601,10 +631,12 @@ void handle_got_event(HANDLE event)
 
     if (h->u.g.moribund) {
        /*
-        * A moribund handle is already treated as dead from the
-        * external user's point of view, so do nothing with the
-        * actual event. Just signal the thread to die if
-        * necessary, or destroy the handle if not.
+        * A moribund handle is one which we have either already
+        * signalled to die, or are waiting until its current I/O op
+        * completes to do so. Either way, it's treated as already
+        * dead from the external user's point of view, so we ignore
+        * the actual I/O result. We just signal the thread to die if
+        * we haven't yet done so, or destroy the handle if not.
         */
        if (h->u.g.done) {
            handle_destroy(h);