summaryrefslogtreecommitdiff
path: root/Modules/_winapi.c
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/_winapi.c')
-rw-r--r--Modules/_winapi.c43
1 files changed, 33 insertions, 10 deletions
diff --git a/Modules/_winapi.c b/Modules/_winapi.c
index c53d55a535..724a4789f4 100644
--- a/Modules/_winapi.c
+++ b/Modules/_winapi.c
@@ -62,6 +62,8 @@
#define T_HANDLE T_POINTER
+#define DWORD_MAX 4294967295U
+
/* Grab CancelIoEx dynamically from kernel32 */
static int has_CancelIoEx = -1;
static BOOL (CALLBACK *Py_CancelIoEx)(HANDLE, LPOVERLAPPED);
@@ -105,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)
@@ -1142,7 +1164,7 @@ winapi_WriteFile(PyObject *self, PyObject *args, PyObject *kwds)
HANDLE handle;
Py_buffer _buf, *buf;
PyObject *bufobj;
- DWORD written;
+ DWORD len, written;
BOOL ret;
int use_overlapped = 0;
DWORD err;
@@ -1170,7 +1192,8 @@ winapi_WriteFile(PyObject *self, PyObject *args, PyObject *kwds)
}
Py_BEGIN_ALLOW_THREADS
- ret = WriteFile(handle, buf->buf, buf->len, &written,
+ len = (DWORD)Py_MIN(buf->len, DWORD_MAX);
+ ret = WriteFile(handle, buf->buf, len, &written,
overlapped ? &overlapped->overlapped : NULL);
Py_END_ALLOW_THREADS