Commit 4860f01a authored by Tony Roberts's avatar Tony Roberts Committed by Steve Dower

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.
parent 2de576e1
GIL is released while calling functions that acquire Windows loader lock.
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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);
}
......
......@@ -984,10 +984,12 @@ winreg_DeleteKeyEx_impl(PyObject *module, HKEY key,
/* Only available on 64bit platforms, so we must load it
dynamically. */
Py_BEGIN_ALLOW_THREADS
hMod = GetModuleHandleW(L"advapi32.dll");
if (hMod)
pfn = (RDKEFunc)GetProcAddress(hMod,
"RegDeleteKeyExW");
Py_END_ALLOW_THREADS
if (!pfn) {
PyErr_SetString(PyExc_NotImplementedError,
"not implemented on this platform");
......@@ -1714,10 +1716,12 @@ winreg_DisableReflectionKey_impl(PyObject *module, HKEY key)
/* Only available on 64bit platforms, so we must load it
dynamically.*/
Py_BEGIN_ALLOW_THREADS
hMod = GetModuleHandleW(L"advapi32.dll");
if (hMod)
pfn = (RDRKFunc)GetProcAddress(hMod,
"RegDisableReflectionKey");
Py_END_ALLOW_THREADS
if (!pfn) {
PyErr_SetString(PyExc_NotImplementedError,
"not implemented on this platform");
......@@ -1757,10 +1761,12 @@ winreg_EnableReflectionKey_impl(PyObject *module, HKEY key)
/* Only available on 64bit platforms, so we must load it
dynamically.*/
Py_BEGIN_ALLOW_THREADS
hMod = GetModuleHandleW(L"advapi32.dll");
if (hMod)
pfn = (RERKFunc)GetProcAddress(hMod,
"RegEnableReflectionKey");
Py_END_ALLOW_THREADS
if (!pfn) {
PyErr_SetString(PyExc_NotImplementedError,
"not implemented on this platform");
......@@ -1799,10 +1805,12 @@ winreg_QueryReflectionKey_impl(PyObject *module, HKEY key)
/* Only available on 64bit platforms, so we must load it
dynamically.*/
Py_BEGIN_ALLOW_THREADS
hMod = GetModuleHandleW(L"advapi32.dll");
if (hMod)
pfn = (RQRKFunc)GetProcAddress(hMod,
"RegQueryReflectionKey");
Py_END_ALLOW_THREADS
if (!pfn) {
PyErr_SetString(PyExc_NotImplementedError,
"not implemented on this platform");
......
......@@ -218,8 +218,10 @@ dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix,
/* We use LoadLibraryEx so Windows looks for dependent DLLs
in directory of pathname first. */
/* XXX This call doesn't exist in Windows CE */
Py_BEGIN_ALLOW_THREADS
hDLL = LoadLibraryExW(wpathname, NULL,
LOAD_WITH_ALTERED_SEARCH_PATH);
Py_END_ALLOW_THREADS
#if HAVE_SXS
_Py_DeactivateActCtx(cookie);
#endif
......@@ -298,11 +300,15 @@ dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix,
"Module use of %.150s conflicts "
"with this version of Python.",
import_python);
Py_BEGIN_ALLOW_THREADS
FreeLibrary(hDLL);
Py_END_ALLOW_THREADS
return NULL;
}
}
Py_BEGIN_ALLOW_THREADS
p = GetProcAddress(hDLL, funcname);
Py_END_ALLOW_THREADS
}
return p;
......
......@@ -1159,7 +1159,9 @@ sys_getwindowsversion_impl(PyObject *module)
// We need to read the version info from a system file resource
// to accurately identify the OS version. If we fail for any reason,
// just return whatever GetVersion said.
Py_BEGIN_ALLOW_THREADS
hKernel32 = GetModuleHandleW(L"kernel32.dll");
Py_END_ALLOW_THREADS
if (hKernel32 && GetModuleFileNameW(hKernel32, kernel32_path, MAX_PATH) &&
(verblock_size = GetFileVersionInfoSizeW(kernel32_path, NULL)) &&
(verblock = PyMem_RawMalloc(verblock_size))) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment