diff options
author | Tony Roberts <tony@pyxll.com> | 2019-02-02 17:16:42 (GMT) |
---|---|---|
committer | Steve Dower <steve.dower@microsoft.com> | 2019-02-02 17:16:42 (GMT) |
commit | 4860f01ac0f07cdc8fc0cc27c33f5a64e5cfec9f (patch) | |
tree | 18e9232f27d8bee1c9a8139937b69ec013a19abf /Modules | |
parent | 2de576e16d42ce43698d384d0dd46ba6cf165424 (diff) | |
download | cpython-4860f01ac0f07cdc8fc0cc27c33f5a64e5cfec9f.zip cpython-4860f01ac0f07cdc8fc0cc27c33f5a64e5cfec9f.tar.gz cpython-4860f01ac0f07cdc8fc0cc27c33f5a64e5cfec9f.tar.bz2 |
bpo-33895: Relase GIL while calling functions that acquire Windows loader lock (GH-7789)
LoadLibrary, GetProcAddress, FreeLibrary and GetModuleHandle acquire the system loader lock. Calling these while holding the GIL will cause a deadlock on the rare occasion that another thread is detaching and needs to destroy its thread state at the same time.
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_ctypes/_ctypes.c | 13 | ||||
-rw-r--r-- | Modules/_ctypes/callproc.c | 11 | ||||
-rw-r--r-- | Modules/overlapped.c | 2 | ||||
-rw-r--r-- | Modules/posixmodule.c | 11 |
4 files changed, 31 insertions, 6 deletions
diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index cc4aab7..0d95d2b 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -678,7 +678,9 @@ CDataType_in_dll(PyObject *type, PyObject *args) } #ifdef MS_WIN32 + Py_BEGIN_ALLOW_THREADS address = (void *)GetProcAddress(handle, name); + Py_END_ALLOW_THREADS if (!address) { PyErr_Format(PyExc_ValueError, "symbol '%s' not found", @@ -3243,18 +3245,23 @@ static PyGetSetDef PyCFuncPtr_getsets[] = { #ifdef MS_WIN32 static PPROC FindAddress(void *handle, const char *name, PyObject *type) { + PPROC address; #ifdef MS_WIN64 /* win64 has no stdcall calling conv, so it should also not have the name mangling of it. */ - return (PPROC)GetProcAddress(handle, name); + Py_BEGIN_ALLOW_THREADS + address = (PPROC)GetProcAddress(handle, name); + Py_END_ALLOW_THREADS + return address; #else - PPROC address; char *mangled_name; int i; StgDictObject *dict; + Py_BEGIN_ALLOW_THREADS address = (PPROC)GetProcAddress(handle, name); + Py_END_ALLOW_THREADS if (address) return address; if (((size_t)name & ~0xFFFF) == 0) { @@ -3275,7 +3282,9 @@ static PPROC FindAddress(void *handle, const char *name, PyObject *type) return NULL; for (i = 0; i < 32; ++i) { sprintf(mangled_name, "_%s@%d", name, i*4); + Py_BEGIN_ALLOW_THREADS address = (PPROC)GetProcAddress(handle, mangled_name); + Py_END_ALLOW_THREADS if (address) return address; } diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index bed5364..9bcc955 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -1286,7 +1286,10 @@ static PyObject *load_library(PyObject *self, PyObject *args) if (!name) return NULL; + Py_BEGIN_ALLOW_THREADS hMod = LoadLibraryW(name); + Py_END_ALLOW_THREADS + if (!hMod) return PyErr_SetFromWindowsErr(GetLastError()); #ifdef _WIN64 @@ -1303,9 +1306,15 @@ Free the handle of an executable previously loaded by LoadLibrary.\n"; static PyObject *free_library(PyObject *self, PyObject *args) { void *hMod; + BOOL result; if (!PyArg_ParseTuple(args, "O&:FreeLibrary", &_parse_voidp, &hMod)) return NULL; - if (!FreeLibrary((HMODULE)hMod)) + + Py_BEGIN_ALLOW_THREADS + result = FreeLibrary((HMODULE)hMod); + Py_END_ALLOW_THREADS + + if (!result) return PyErr_SetFromWindowsErr(GetLastError()); Py_RETURN_NONE; } diff --git a/Modules/overlapped.c b/Modules/overlapped.c index ef4390b..e5a209b 100644 --- a/Modules/overlapped.c +++ b/Modules/overlapped.c @@ -127,8 +127,10 @@ initialize_function_pointers(void) closesocket(s); /* On WinXP we will have Py_CancelIoEx == NULL */ + Py_BEGIN_ALLOW_THREADS hKernel32 = GetModuleHandle("KERNEL32"); *(FARPROC *)&Py_CancelIoEx = GetProcAddress(hKernel32, "CancelIoEx"); + Py_END_ALLOW_THREADS return 0; } diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 0f6bd14..931c0d3 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -7749,9 +7749,13 @@ check_CreateSymbolicLink(void) /* only recheck */ if (Py_CreateSymbolicLinkW) return 1; + + Py_BEGIN_ALLOW_THREADS hKernel32 = GetModuleHandleW(L"KERNEL32"); *(FARPROC*)&Py_CreateSymbolicLinkW = GetProcAddress(hKernel32, "CreateSymbolicLinkW"); + Py_END_ALLOW_THREADS + return Py_CreateSymbolicLinkW != NULL; } @@ -11288,7 +11292,6 @@ check_ShellExecute() the system SHELL32.DLL, even if there is another SHELL32.DLL in the DLL search path. */ hShell32 = LoadLibraryW(L"SHELL32"); - Py_END_ALLOW_THREADS if (hShell32) { *(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32, "ShellExecuteW"); @@ -11296,6 +11299,7 @@ check_ShellExecute() } else { has_ShellExecute = 0; } + Py_END_ALLOW_THREADS } return has_ShellExecute; } @@ -11909,11 +11913,12 @@ os_cpu_count_impl(PyObject *module) /* Vista is supported and the GetMaximumProcessorCount API is Win7+ Need to fallback to Vista behavior if this call isn't present */ HINSTANCE hKernel32; - hKernel32 = GetModuleHandleW(L"KERNEL32"); - static DWORD(CALLBACK *_GetMaximumProcessorCount)(WORD) = NULL; + Py_BEGIN_ALLOW_THREADS + hKernel32 = GetModuleHandleW(L"KERNEL32"); *(FARPROC*)&_GetMaximumProcessorCount = GetProcAddress(hKernel32, "GetMaximumProcessorCount"); + Py_END_ALLOW_THREADS if (_GetMaximumProcessorCount != NULL) { ncpu = _GetMaximumProcessorCount(ALL_PROCESSOR_GROUPS); } |