diff -r 0a71d29b970a Modules/_winapi.c --- a/Modules/_winapi.c Mon Feb 03 00:35:46 2014 +0100 +++ b/Modules/_winapi.c Mon Feb 03 02:20:54 2014 +0100 @@ -115,16 +115,8 @@ overlapped_dealloc(OverlappedObject *sel { /* 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 + else if (_Py_Finalizing != NULL + && GetLastError() == ERROR_IO_INCOMPLETE) { /* The operation is still pending, but the process is probably about to exit, so we need not worry too much @@ -136,6 +128,15 @@ overlapped_dealloc(OverlappedObject *sel SetLastError(err); return; } + else + { + /* 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); + } } CloseHandle(self->overlapped.hEvent); diff -r 0a71d29b970a Modules/overlapped.c --- a/Modules/overlapped.c Mon Feb 03 00:35:46 2014 +0100 +++ b/Modules/overlapped.c Mon Feb 03 02:20:54 2014 +0100 @@ -536,7 +536,7 @@ static void Overlapped_dealloc(OverlappedObject *self) { DWORD bytes; - DWORD olderr = GetLastError(); + DWORD err, olderr = GetLastError(); BOOL wait = FALSE; BOOL ret; @@ -551,12 +551,24 @@ Overlapped_dealloc(OverlappedObject *sel &bytes, wait); Py_END_ALLOW_THREADS - switch (ret ? ERROR_SUCCESS : GetLastError()) { + err = ret ? ERROR_SUCCESS : GetLastError(); + switch (err) { case ERROR_SUCCESS: case ERROR_NOT_FOUND: case ERROR_OPERATION_ABORTED: break; default: + if (Py_Finalizing != NULL && err == ERROR_IO_INCOMPLETE) { + /* 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; + } PyErr_Format( PyExc_RuntimeError, "%R still has pending operation at "