New submission from Steve Dower <steve.do...@python.org>:

Most Win32 API calls are made within Py_BEGIN_ALLOW_THREADS blocks, as they do 
not access Python objects and so we can release the GIL.

However, in general, error handling occurs after the Py_END_ALLOW_THREADS line. 
Due to the design of the Win32 API, the pattern looks like this:

    Py_BEGIN_ALLOW_THREADS
    ret = ApiCall(...);
    Py_END_ALLOW_THREADS
    if (FAILED(ret)) {
        error_code = GetLastError();
    }

However, Py_END_ALLOW_THREADS also makes Win32 API calls (to acquire the GIL), 
and if any of these fail then the error code may be overwritten.

Failures in Py_END_ALLOW_THREADS are either fatal (in which case we don't care 
about the preceding error any more) or signal a retry (in which case we *do* 
care about the preceding error), but in the latter case we may have lost the 
error code.

Further, while Win32 APIs are not _supposed_ to set the last error to 
ERROR_SUCCESS (0) when they succeed, some occasionally do.

We should update Py_END_ALLOW_THREADS to preserve the last error code when 
necessary. Ideally, if we don't have to do any work to reacquire the GIL, we 
shouldn't do any work to preserve the error code either.

----------
components: Windows
messages: 313447
nosy: paul.moore, steve.dower, tim.golden, zach.ware
priority: normal
severity: normal
stage: test needed
status: open
title: GetLastError() may be overwritten by Py_END_ALLOW_THREADS
type: behavior
versions: Python 3.6, Python 3.7, Python 3.8

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue33030>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to