mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
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.
This commit is contained in:
parent
2de576e16d
commit
4860f01ac0
8 changed files with 48 additions and 6 deletions
|
@ -0,0 +1 @@
|
||||||
|
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
|
#ifdef MS_WIN32
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
address = (void *)GetProcAddress(handle, name);
|
address = (void *)GetProcAddress(handle, name);
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
if (!address) {
|
if (!address) {
|
||||||
PyErr_Format(PyExc_ValueError,
|
PyErr_Format(PyExc_ValueError,
|
||||||
"symbol '%s' not found",
|
"symbol '%s' not found",
|
||||||
|
@ -3243,18 +3245,23 @@ static PyGetSetDef PyCFuncPtr_getsets[] = {
|
||||||
#ifdef MS_WIN32
|
#ifdef MS_WIN32
|
||||||
static PPROC FindAddress(void *handle, const char *name, PyObject *type)
|
static PPROC FindAddress(void *handle, const char *name, PyObject *type)
|
||||||
{
|
{
|
||||||
|
PPROC address;
|
||||||
#ifdef MS_WIN64
|
#ifdef MS_WIN64
|
||||||
/* win64 has no stdcall calling conv, so it should
|
/* win64 has no stdcall calling conv, so it should
|
||||||
also not have the name mangling of it.
|
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
|
#else
|
||||||
PPROC address;
|
|
||||||
char *mangled_name;
|
char *mangled_name;
|
||||||
int i;
|
int i;
|
||||||
StgDictObject *dict;
|
StgDictObject *dict;
|
||||||
|
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
address = (PPROC)GetProcAddress(handle, name);
|
address = (PPROC)GetProcAddress(handle, name);
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
if (address)
|
if (address)
|
||||||
return address;
|
return address;
|
||||||
if (((size_t)name & ~0xFFFF) == 0) {
|
if (((size_t)name & ~0xFFFF) == 0) {
|
||||||
|
@ -3275,7 +3282,9 @@ static PPROC FindAddress(void *handle, const char *name, PyObject *type)
|
||||||
return NULL;
|
return NULL;
|
||||||
for (i = 0; i < 32; ++i) {
|
for (i = 0; i < 32; ++i) {
|
||||||
sprintf(mangled_name, "_%s@%d", name, i*4);
|
sprintf(mangled_name, "_%s@%d", name, i*4);
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
address = (PPROC)GetProcAddress(handle, mangled_name);
|
address = (PPROC)GetProcAddress(handle, mangled_name);
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
if (address)
|
if (address)
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1286,7 +1286,10 @@ static PyObject *load_library(PyObject *self, PyObject *args)
|
||||||
if (!name)
|
if (!name)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
hMod = LoadLibraryW(name);
|
hMod = LoadLibraryW(name);
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
if (!hMod)
|
if (!hMod)
|
||||||
return PyErr_SetFromWindowsErr(GetLastError());
|
return PyErr_SetFromWindowsErr(GetLastError());
|
||||||
#ifdef _WIN64
|
#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)
|
static PyObject *free_library(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
void *hMod;
|
void *hMod;
|
||||||
|
BOOL result;
|
||||||
if (!PyArg_ParseTuple(args, "O&:FreeLibrary", &_parse_voidp, &hMod))
|
if (!PyArg_ParseTuple(args, "O&:FreeLibrary", &_parse_voidp, &hMod))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (!FreeLibrary((HMODULE)hMod))
|
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
|
result = FreeLibrary((HMODULE)hMod);
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
|
if (!result)
|
||||||
return PyErr_SetFromWindowsErr(GetLastError());
|
return PyErr_SetFromWindowsErr(GetLastError());
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,8 +127,10 @@ initialize_function_pointers(void)
|
||||||
closesocket(s);
|
closesocket(s);
|
||||||
|
|
||||||
/* On WinXP we will have Py_CancelIoEx == NULL */
|
/* On WinXP we will have Py_CancelIoEx == NULL */
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
hKernel32 = GetModuleHandle("KERNEL32");
|
hKernel32 = GetModuleHandle("KERNEL32");
|
||||||
*(FARPROC *)&Py_CancelIoEx = GetProcAddress(hKernel32, "CancelIoEx");
|
*(FARPROC *)&Py_CancelIoEx = GetProcAddress(hKernel32, "CancelIoEx");
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7749,9 +7749,13 @@ check_CreateSymbolicLink(void)
|
||||||
/* only recheck */
|
/* only recheck */
|
||||||
if (Py_CreateSymbolicLinkW)
|
if (Py_CreateSymbolicLinkW)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
hKernel32 = GetModuleHandleW(L"KERNEL32");
|
hKernel32 = GetModuleHandleW(L"KERNEL32");
|
||||||
*(FARPROC*)&Py_CreateSymbolicLinkW = GetProcAddress(hKernel32,
|
*(FARPROC*)&Py_CreateSymbolicLinkW = GetProcAddress(hKernel32,
|
||||||
"CreateSymbolicLinkW");
|
"CreateSymbolicLinkW");
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
|
|
||||||
return Py_CreateSymbolicLinkW != NULL;
|
return Py_CreateSymbolicLinkW != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11288,7 +11292,6 @@ check_ShellExecute()
|
||||||
the system SHELL32.DLL, even if there is another SHELL32.DLL
|
the system SHELL32.DLL, even if there is another SHELL32.DLL
|
||||||
in the DLL search path. */
|
in the DLL search path. */
|
||||||
hShell32 = LoadLibraryW(L"SHELL32");
|
hShell32 = LoadLibraryW(L"SHELL32");
|
||||||
Py_END_ALLOW_THREADS
|
|
||||||
if (hShell32) {
|
if (hShell32) {
|
||||||
*(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
|
*(FARPROC*)&Py_ShellExecuteW = GetProcAddress(hShell32,
|
||||||
"ShellExecuteW");
|
"ShellExecuteW");
|
||||||
|
@ -11296,6 +11299,7 @@ check_ShellExecute()
|
||||||
} else {
|
} else {
|
||||||
has_ShellExecute = 0;
|
has_ShellExecute = 0;
|
||||||
}
|
}
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
}
|
}
|
||||||
return has_ShellExecute;
|
return has_ShellExecute;
|
||||||
}
|
}
|
||||||
|
@ -11909,11 +11913,12 @@ os_cpu_count_impl(PyObject *module)
|
||||||
/* Vista is supported and the GetMaximumProcessorCount API is Win7+
|
/* Vista is supported and the GetMaximumProcessorCount API is Win7+
|
||||||
Need to fallback to Vista behavior if this call isn't present */
|
Need to fallback to Vista behavior if this call isn't present */
|
||||||
HINSTANCE hKernel32;
|
HINSTANCE hKernel32;
|
||||||
hKernel32 = GetModuleHandleW(L"KERNEL32");
|
|
||||||
|
|
||||||
static DWORD(CALLBACK *_GetMaximumProcessorCount)(WORD) = NULL;
|
static DWORD(CALLBACK *_GetMaximumProcessorCount)(WORD) = NULL;
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
|
hKernel32 = GetModuleHandleW(L"KERNEL32");
|
||||||
*(FARPROC*)&_GetMaximumProcessorCount = GetProcAddress(hKernel32,
|
*(FARPROC*)&_GetMaximumProcessorCount = GetProcAddress(hKernel32,
|
||||||
"GetMaximumProcessorCount");
|
"GetMaximumProcessorCount");
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
if (_GetMaximumProcessorCount != NULL) {
|
if (_GetMaximumProcessorCount != NULL) {
|
||||||
ncpu = _GetMaximumProcessorCount(ALL_PROCESSOR_GROUPS);
|
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
|
/* Only available on 64bit platforms, so we must load it
|
||||||
dynamically. */
|
dynamically. */
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
hMod = GetModuleHandleW(L"advapi32.dll");
|
hMod = GetModuleHandleW(L"advapi32.dll");
|
||||||
if (hMod)
|
if (hMod)
|
||||||
pfn = (RDKEFunc)GetProcAddress(hMod,
|
pfn = (RDKEFunc)GetProcAddress(hMod,
|
||||||
"RegDeleteKeyExW");
|
"RegDeleteKeyExW");
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
if (!pfn) {
|
if (!pfn) {
|
||||||
PyErr_SetString(PyExc_NotImplementedError,
|
PyErr_SetString(PyExc_NotImplementedError,
|
||||||
"not implemented on this platform");
|
"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
|
/* Only available on 64bit platforms, so we must load it
|
||||||
dynamically.*/
|
dynamically.*/
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
hMod = GetModuleHandleW(L"advapi32.dll");
|
hMod = GetModuleHandleW(L"advapi32.dll");
|
||||||
if (hMod)
|
if (hMod)
|
||||||
pfn = (RDRKFunc)GetProcAddress(hMod,
|
pfn = (RDRKFunc)GetProcAddress(hMod,
|
||||||
"RegDisableReflectionKey");
|
"RegDisableReflectionKey");
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
if (!pfn) {
|
if (!pfn) {
|
||||||
PyErr_SetString(PyExc_NotImplementedError,
|
PyErr_SetString(PyExc_NotImplementedError,
|
||||||
"not implemented on this platform");
|
"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
|
/* Only available on 64bit platforms, so we must load it
|
||||||
dynamically.*/
|
dynamically.*/
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
hMod = GetModuleHandleW(L"advapi32.dll");
|
hMod = GetModuleHandleW(L"advapi32.dll");
|
||||||
if (hMod)
|
if (hMod)
|
||||||
pfn = (RERKFunc)GetProcAddress(hMod,
|
pfn = (RERKFunc)GetProcAddress(hMod,
|
||||||
"RegEnableReflectionKey");
|
"RegEnableReflectionKey");
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
if (!pfn) {
|
if (!pfn) {
|
||||||
PyErr_SetString(PyExc_NotImplementedError,
|
PyErr_SetString(PyExc_NotImplementedError,
|
||||||
"not implemented on this platform");
|
"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
|
/* Only available on 64bit platforms, so we must load it
|
||||||
dynamically.*/
|
dynamically.*/
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
hMod = GetModuleHandleW(L"advapi32.dll");
|
hMod = GetModuleHandleW(L"advapi32.dll");
|
||||||
if (hMod)
|
if (hMod)
|
||||||
pfn = (RQRKFunc)GetProcAddress(hMod,
|
pfn = (RQRKFunc)GetProcAddress(hMod,
|
||||||
"RegQueryReflectionKey");
|
"RegQueryReflectionKey");
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
if (!pfn) {
|
if (!pfn) {
|
||||||
PyErr_SetString(PyExc_NotImplementedError,
|
PyErr_SetString(PyExc_NotImplementedError,
|
||||||
"not implemented on this platform");
|
"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
|
/* We use LoadLibraryEx so Windows looks for dependent DLLs
|
||||||
in directory of pathname first. */
|
in directory of pathname first. */
|
||||||
/* XXX This call doesn't exist in Windows CE */
|
/* XXX This call doesn't exist in Windows CE */
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
hDLL = LoadLibraryExW(wpathname, NULL,
|
hDLL = LoadLibraryExW(wpathname, NULL,
|
||||||
LOAD_WITH_ALTERED_SEARCH_PATH);
|
LOAD_WITH_ALTERED_SEARCH_PATH);
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
#if HAVE_SXS
|
#if HAVE_SXS
|
||||||
_Py_DeactivateActCtx(cookie);
|
_Py_DeactivateActCtx(cookie);
|
||||||
#endif
|
#endif
|
||||||
|
@ -298,11 +300,15 @@ dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix,
|
||||||
"Module use of %.150s conflicts "
|
"Module use of %.150s conflicts "
|
||||||
"with this version of Python.",
|
"with this version of Python.",
|
||||||
import_python);
|
import_python);
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
FreeLibrary(hDLL);
|
FreeLibrary(hDLL);
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
p = GetProcAddress(hDLL, funcname);
|
p = GetProcAddress(hDLL, funcname);
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
}
|
}
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
|
|
|
@ -1159,7 +1159,9 @@ sys_getwindowsversion_impl(PyObject *module)
|
||||||
// We need to read the version info from a system file resource
|
// We need to read the version info from a system file resource
|
||||||
// to accurately identify the OS version. If we fail for any reason,
|
// to accurately identify the OS version. If we fail for any reason,
|
||||||
// just return whatever GetVersion said.
|
// just return whatever GetVersion said.
|
||||||
|
Py_BEGIN_ALLOW_THREADS
|
||||||
hKernel32 = GetModuleHandleW(L"kernel32.dll");
|
hKernel32 = GetModuleHandleW(L"kernel32.dll");
|
||||||
|
Py_END_ALLOW_THREADS
|
||||||
if (hKernel32 && GetModuleFileNameW(hKernel32, kernel32_path, MAX_PATH) &&
|
if (hKernel32 && GetModuleFileNameW(hKernel32, kernel32_path, MAX_PATH) &&
|
||||||
(verblock_size = GetFileVersionInfoSizeW(kernel32_path, NULL)) &&
|
(verblock_size = GetFileVersionInfoSizeW(kernel32_path, NULL)) &&
|
||||||
(verblock = PyMem_RawMalloc(verblock_size))) {
|
(verblock = PyMem_RawMalloc(verblock_size))) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue