summaryrefslogtreecommitdiff
path: root/Modules/_ctypes
diff options
context:
space:
mode:
authorTony Roberts <tony@pyxll.com>2019-02-02 18:16:42 +0100
committerSteve Dower <steve.dower@microsoft.com>2019-02-02 09:16:42 -0800
commit4860f01ac0f07cdc8fc0cc27c33f5a64e5cfec9f (patch)
tree18e9232f27d8bee1c9a8139937b69ec013a19abf /Modules/_ctypes
parent2de576e16d42ce43698d384d0dd46ba6cf165424 (diff)
downloadcpython-git-4860f01ac0f07cdc8fc0cc27c33f5a64e5cfec9f.tar.gz
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/_ctypes')
-rw-r--r--Modules/_ctypes/_ctypes.c13
-rw-r--r--Modules/_ctypes/callproc.c11
2 files changed, 21 insertions, 3 deletions
diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c
index cc4aab7389..0d95d2b6f7 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 bed5364020..9bcc9557ec 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;
}