]> granicus.if.org Git - python/commitdiff
Issue #19565: Prevent warnings at shutdown about pending overlapped ops.
authorRichard Oudkerk <shibturn@gmail.com>
Sun, 17 Nov 2013 13:15:51 +0000 (13:15 +0000)
committerRichard Oudkerk <shibturn@gmail.com>
Sun, 17 Nov 2013 13:15:51 +0000 (13:15 +0000)
Modules/_winapi.c

index 20d0063aaf45eccfb6ff8cbf6b3558354c3880e3..724a4789f49fbd089a159ac1732ea4e010991704 100644 (file)
@@ -107,17 +107,37 @@ overlapped_dealloc(OverlappedObject *self)
 {
     DWORD bytes;
     int err = GetLastError();
+
     if (self->pending) {
-        /* make it a programming error to deallocate while operation
-           is pending, even if we can safely cancel it */
         if (check_CancelIoEx() &&
-                Py_CancelIoEx(self->handle, &self->overlapped))
-            GetOverlappedResult(self->handle, &self->overlapped, &bytes, TRUE);
-        PyErr_SetString(PyExc_RuntimeError,
-                        "I/O operations still in flight while destroying "
-                        "Overlapped object, the process may crash");
-        PyErr_WriteUnraisable(NULL);
+            Py_CancelIoEx(self->handle, &self->overlapped) &&
+            GetOverlappedResult(self->handle, &self->overlapped, &bytes, TRUE))
+        {
+            /* The operation is no longer pending -- nothing to do. */
+        }
+        else if (_Py_Finalizing == NULL)
+        {
+            /* The operation is still pending -- give a warning.  This
+               will probably only happen on Windows XP. */
+            PyErr_SetString(PyExc_RuntimeError,
+                            "I/O operations still in flight while destroying "
+                            "Overlapped object, the process may crash");
+            PyErr_WriteUnraisable(NULL);
+        }
+        else
+        {
+            /* The operation is still pending, but the process is
+               probably about to exit, so we need not worry too much
+               about memory leaks.  Leaking self prevents a potential
+               crash.  This can happen when a daemon thread is cleaned
+               up at exit -- see #19565.  We only expect to get here
+               on Windows XP. */
+            CloseHandle(self->overlapped.hEvent);
+            SetLastError(err);
+            return;
+        }
     }
+
     CloseHandle(self->overlapped.hEvent);
     SetLastError(err);
     if (self->write_buffer.obj)