@@ -107,17 +107,37 @@ overlapped_dealloc(OverlappedObject *self)
107107{
108108 DWORD bytes ;
109109 int err = GetLastError ();
110+
110111 if (self -> pending ) {
111- /* make it a programming error to deallocate while operation
112- is pending, even if we can safely cancel it */
113112 if (check_CancelIoEx () &&
114- Py_CancelIoEx (self -> handle , & self -> overlapped ))
115- GetOverlappedResult (self -> handle , & self -> overlapped , & bytes , TRUE);
116- PyErr_SetString (PyExc_RuntimeError ,
117- "I/O operations still in flight while destroying "
118- "Overlapped object, the process may crash" );
119- PyErr_WriteUnraisable (NULL );
113+ Py_CancelIoEx (self -> handle , & self -> overlapped ) &&
114+ GetOverlappedResult (self -> handle , & self -> overlapped , & bytes , TRUE))
115+ {
116+ /* The operation is no longer pending -- nothing to do. */
117+ }
118+ else if (_Py_Finalizing == NULL )
119+ {
120+ /* The operation is still pending -- give a warning. This
121+ will probably only happen on Windows XP. */
122+ PyErr_SetString (PyExc_RuntimeError ,
123+ "I/O operations still in flight while destroying "
124+ "Overlapped object, the process may crash" );
125+ PyErr_WriteUnraisable (NULL );
126+ }
127+ else
128+ {
129+ /* The operation is still pending, but the process is
130+ probably about to exit, so we need not worry too much
131+ about memory leaks. Leaking self prevents a potential
132+ crash. This can happen when a daemon thread is cleaned
133+ up at exit -- see #19565. We only expect to get here
134+ on Windows XP. */
135+ CloseHandle (self -> overlapped .hEvent );
136+ SetLastError (err );
137+ return ;
138+ }
120139 }
140+
121141 CloseHandle (self -> overlapped .hEvent );
122142 SetLastError (err );
123143 if (self -> write_buffer .obj )
0 commit comments