Skip to content

Commit 000a074

Browse files
committed
Modified PyImport_Import and PyImport_ImportModule to always use absolute imports by calling __import__ with an explicit level of 0
Added a new API function PyImport_ImportModuleNoBlock. It solves the problem with dead locks when mixing threads and imports
1 parent 0a83d79 commit 000a074

File tree

19 files changed

+135
-63
lines changed

19 files changed

+135
-63
lines changed

Doc/c-api/utilities.rst

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,8 @@ Importing Modules
183183
single: __all__ (package variable)
184184

185185
This is a simplified interface to :cfunc:`PyImport_ImportModuleEx` below,
186-
leaving the *globals* and *locals* arguments set to *NULL*. When the *name*
186+
leaving the *globals* and *locals* arguments set to *NULL* and *level* set
187+
to 0. When the *name*
187188
argument contains a dot (when it specifies a submodule of a package), the
188189
*fromlist* argument is set to the list ``['*']`` so that the return value is the
189190
named module rather than the top-level package containing it as would otherwise
@@ -198,9 +199,28 @@ Importing Modules
198199
.. versionchanged:: 2.4
199200
failing imports remove incomplete module objects.
200201

202+
.. versionchanged:: 2.6
203+
always use absolute imports
204+
201205
.. index:: single: modules (in module sys)
202206

203207

208+
.. cfunction:: PyObject* PyImport_ImportModuleNoBlock(const char *name)
209+
210+
.. index::
211+
single: `cfunc:PyImport_ImportModule`
212+
213+
This version of `cfunc:PyImport_ImportModule` does not block. It's intended
214+
to be used in C function which import other modules to execute a function.
215+
The import may block if another thread holds the import lock. The function
216+
`cfunc:PyImport_ImportModuleNoBlock` doesn't block. It first tries to fetch
217+
the module from sys.modules and falls back to `cfunc:PyImport_ImportModule`
218+
unless the the lock is hold. In the latter case the function raises an
219+
ImportError.
220+
221+
.. versionadded:: 2.6
222+
223+
204224
.. cfunction:: PyObject* PyImport_ImportModuleEx(char *name, PyObject *globals, PyObject *locals, PyObject *fromlist)
205225

206226
.. index:: builtin: __import__
@@ -218,6 +238,24 @@ Importing Modules
218238
.. versionchanged:: 2.4
219239
failing imports remove incomplete module objects.
220240

241+
.. versionchanged:: 2.6
242+
The function is an alias for `cfunc:PyImport_ImportModuleLevel` with
243+
-1 as level, meaning relative import.
244+
245+
246+
.. cfunction:: PyObject* PyImport_ImportModuleLevel(char *name, PyObject *globals, PyObject *locals, PyObject *fromlist, int level)
247+
248+
Import a module. This is best described by referring to the built-in Python
249+
function :func:`__import__`, as the standard :func:`__import__` function calls
250+
this function directly.
251+
252+
The return value is a new reference to the imported module or top-level package,
253+
or *NULL* with an exception set on failure. Like for :func:`__import__`,
254+
the return value when a submodule of a package was requested is normally the
255+
top-level package, unless a non-empty *fromlist* was given.
256+
257+
..versionadded:: 2.5
258+
221259

222260
.. cfunction:: PyObject* PyImport_Import(PyObject *name)
223261

@@ -230,6 +268,9 @@ Importing Modules
230268
current globals. This means that the import is done using whatever import hooks
231269
are installed in the current environment, e.g. by :mod:`rexec` or :mod:`ihooks`.
232270

271+
.. versionchanged:: 2.6
272+
always use absolute imports
273+
233274

234275
.. cfunction:: PyObject* PyImport_ReloadModule(PyObject *m)
235276

Include/import.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,10 @@ PyAPI_FUNC(PyObject *) PyImport_ExecCodeModuleEx(
1414
PyAPI_FUNC(PyObject *) PyImport_GetModuleDict(void);
1515
PyAPI_FUNC(PyObject *) PyImport_AddModule(const char *name);
1616
PyAPI_FUNC(PyObject *) PyImport_ImportModule(const char *name);
17+
PyAPI_FUNC(PyObject *) PyImport_ImportModuleNoBlock(const char *);
1718
PyAPI_FUNC(PyObject *) PyImport_ImportModuleLevel(char *name,
1819
PyObject *globals, PyObject *locals, PyObject *fromlist, int level);
1920

20-
/* For DLL compatibility */
21-
#undef PyImport_ImportModuleEx
22-
PyAPI_FUNC(PyObject *) PyImport_ImportModuleEx(
23-
char *name, PyObject *globals, PyObject *locals, PyObject *fromlist);
2421
#define PyImport_ImportModuleEx(n, g, l, f) \
2522
PyImport_ImportModuleLevel(n, g, l, f, -1)
2623

Include/py_curses.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ static void **PyCurses_API;
9090

9191
#define import_curses() \
9292
{ \
93-
PyObject *module = PyImport_ImportModule("_curses"); \
93+
PyObject *module = PyImport_ImportModuleNoBlock("_curses"); \
9494
if (module != NULL) { \
9595
PyObject *module_dict = PyModule_GetDict(module); \
9696
PyObject *c_api_object = PyDict_GetItemString(module_dict, "_C_API"); \

Mac/Modules/MacOS.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ MacOS_GetErrorString(PyObject *self, PyObject *args)
357357
PyObject *m, *rv;
358358
errors_loaded = 1;
359359

360-
m = PyImport_ImportModule("macresource");
360+
m = PyImport_ImportModuleNoBlock("macresource");
361361
if (!m) {
362362
if (Py_VerboseFlag)
363363
PyErr_Print();

Misc/NEWS

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,10 @@ Core and builtins
1414

1515
- Issue #1640: Added math.isinf() and math.isnan() functions.
1616

17-
- Issue #1726: Remove Python/atof.c from PCBuild/pythoncore.vcproj
18-
19-
- Removed PCbuild8/ directory and added a new build directory for VS 2005
20-
based on the VS 2008 build directory to PC/VS8.0. The script
21-
PCbuild/vs8to9.py was added to sync changes from PCbuild to PC/VS8.0.
22-
23-
- Moved PCbuild/ directory for VS 2003 to PC/VS7.1 and renamed PCBuild9/
24-
directory to PCBuild/.
25-
26-
- Issue #1629: Renamed Py_Size, Py_Type and Py_Refcnt to Py_SIZE, Py_TYPE
27-
and Py_REFCNT.
28-
2917
- Issue #1635: Platform independent creation and representation of NaN
3018
and INF. float("nan"), float("inf") and float("-inf") now work on every
3119
platform with IEEE 754 semantics.
3220

33-
- Added case insensitive comparsion methods ``PyOS_stricmp(char*, char*)``
34-
and ``PyOS_strnicmp(char*, char*, Py_ssize_t)``.
35-
3621
- Compiler now generates simpler and faster code for dictionary literals.
3722
The oparg for BUILD_MAP now indicates an estimated dictionary size.
3823
There is a new opcode, STORE_MAP, for adding entries to the dictionary.
@@ -1165,6 +1150,15 @@ Tools/Demos
11651150
Build
11661151
-----
11671152

1153+
- Issue #1726: Remove Python/atof.c from PCBuild/pythoncore.vcproj
1154+
1155+
- Removed PCbuild8/ directory and added a new build directory for VS 2005
1156+
based on the VS 2008 build directory to PC/VS8.0. The script
1157+
PCbuild/vs8to9.py was added to sync changes from PCbuild to PC/VS8.0.
1158+
1159+
- Moved PCbuild/ directory for VS 2003 to PC/VS7.1 and renamed PCBuild9/
1160+
directory to PCBuild/.
1161+
11681162
- Bug #1699: Define _BSD_SOURCE only on OpenBSD.
11691163

11701164
- Bug #1608: use -fwrapv when GCC supports it. This is important,
@@ -1225,6 +1219,18 @@ Build
12251219
C API
12261220
-----
12271221

1222+
- Added a new API function ``PyImport_ImportModuleNoBlock``.
1223+
1224+
- ``PyImport_Import`` and ``PyImport_ImportModule`` now always do absolute
1225+
imports. In earlier versions they might have used relative imports under
1226+
some conditions.
1227+
1228+
- Issue #1629: Renamed Py_Size, Py_Type and Py_Refcnt to Py_SIZE, Py_TYPE
1229+
and Py_REFCNT.
1230+
1231+
- Added case insensitive comparsion methods ``PyOS_stricmp(char*, char*)``
1232+
and ``PyOS_strnicmp(char*, char*, Py_ssize_t)``.
1233+
12281234
- Bug #1542693: remove semi-colon at end of PyImport_ImportModuleEx macro
12291235
so it can be used as an expression.
12301236

Modules/_ctypes/callbacks.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ long Call_GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
370370
if (context == NULL)
371371
context = PyString_FromString("_ctypes.DllGetClassObject");
372372

373-
mod = PyImport_ImportModule("ctypes");
373+
mod = PyImport_ImportModuleNoBlock("ctypes");
374374
if (!mod) {
375375
PyErr_WriteUnraisable(context ? context : Py_None);
376376
/* There has been a warning before about this already */
@@ -449,7 +449,7 @@ long Call_CanUnloadNow(void)
449449
if (context == NULL)
450450
context = PyString_FromString("_ctypes.DllCanUnloadNow");
451451

452-
mod = PyImport_ImportModule("ctypes");
452+
mod = PyImport_ImportModuleNoBlock("ctypes");
453453
if (!mod) {
454454
/* OutputDebugString("Could not import ctypes"); */
455455
/* We assume that this error can only occur when shutting

Modules/_cursesmodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2255,7 +2255,7 @@ static int
22552255
update_lines_cols(void)
22562256
{
22572257
PyObject *o;
2258-
PyObject *m = PyImport_ImportModule("curses");
2258+
PyObject *m = PyImport_ImportModuleNoBlock("curses");
22592259

22602260
if (!m)
22612261
return 0;

Modules/cjkcodecs/cjkcodecs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ getmultibytecodec(void)
245245
static PyObject *cofunc = NULL;
246246

247247
if (cofunc == NULL) {
248-
PyObject *mod = PyImport_ImportModule("_multibytecodec");
248+
PyObject *mod = PyImport_ImportModuleNoBlock("_multibytecodec");
249249
if (mod == NULL)
250250
return NULL;
251251
cofunc = PyObject_GetAttrString(mod, "__create_codec");

Modules/datetimemodule.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1305,7 +1305,7 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
13051305
if (_PyString_Resize(&newfmt, usednew) < 0)
13061306
goto Done;
13071307
{
1308-
PyObject *time = PyImport_ImportModule("time");
1308+
PyObject *time = PyImport_ImportModuleNoBlock("time");
13091309
if (time == NULL)
13101310
goto Done;
13111311
result = PyObject_CallMethod(time, "strftime", "OO",
@@ -1353,7 +1353,7 @@ static PyObject *
13531353
time_time(void)
13541354
{
13551355
PyObject *result = NULL;
1356-
PyObject *time = PyImport_ImportModule("time");
1356+
PyObject *time = PyImport_ImportModuleNoBlock("time");
13571357

13581358
if (time != NULL) {
13591359
result = PyObject_CallMethod(time, "time", "()");
@@ -1371,7 +1371,7 @@ build_struct_time(int y, int m, int d, int hh, int mm, int ss, int dstflag)
13711371
PyObject *time;
13721372
PyObject *result = NULL;
13731373

1374-
time = PyImport_ImportModule("time");
1374+
time = PyImport_ImportModuleNoBlock("time");
13751375
if (time != NULL) {
13761376
result = PyObject_CallMethod(time, "struct_time",
13771377
"((iiiiiiiii))",
@@ -3827,7 +3827,7 @@ datetime_strptime(PyObject *cls, PyObject *args)
38273827
if (!PyArg_ParseTuple(args, "ss:strptime", &string, &format))
38283828
return NULL;
38293829

3830-
if ((module = PyImport_ImportModule("time")) == NULL)
3830+
if ((module = PyImport_ImportModuleNoBlock("time")) == NULL)
38313831
return NULL;
38323832
obj = PyObject_CallMethod(module, "strptime", "ss", string, format);
38333833
Py_DECREF(module);

Modules/gcmodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1236,7 +1236,7 @@ initgc(void)
12361236
* the import and triggers an assertion.
12371237
*/
12381238
if (tmod == NULL) {
1239-
tmod = PyImport_ImportModule("time");
1239+
tmod = PyImport_ImportModuleNoBlock("time");
12401240
if (tmod == NULL)
12411241
PyErr_Clear();
12421242
}

0 commit comments

Comments
 (0)