mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	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
This commit is contained in:
		
							parent
							
								
									0a83d79268
								
							
						
					
					
						commit
						000a074c95
					
				
					 19 changed files with 135 additions and 63 deletions
				
			
		|  | @ -183,7 +183,8 @@ Importing Modules | ||||||
|       single: __all__ (package variable) |       single: __all__ (package variable) | ||||||
| 
 | 
 | ||||||
|    This is a simplified interface to :cfunc:`PyImport_ImportModuleEx` below, |    This is a simplified interface to :cfunc:`PyImport_ImportModuleEx` below, | ||||||
|    leaving the *globals* and *locals* arguments set to *NULL*.  When the *name* |    leaving the *globals* and *locals* arguments set to *NULL* and *level* set | ||||||
|  |    to 0.  When the *name* | ||||||
|    argument contains a dot (when it specifies a submodule of a package), the |    argument contains a dot (when it specifies a submodule of a package), the | ||||||
|    *fromlist* argument is set to the list ``['*']`` so that the return value is the |    *fromlist* argument is set to the list ``['*']`` so that the return value is the | ||||||
|    named module rather than the top-level package containing it as would otherwise |    named module rather than the top-level package containing it as would otherwise | ||||||
|  | @ -198,9 +199,28 @@ Importing Modules | ||||||
|    .. versionchanged:: 2.4 |    .. versionchanged:: 2.4 | ||||||
|       failing imports remove incomplete module objects. |       failing imports remove incomplete module objects. | ||||||
| 
 | 
 | ||||||
|  |    .. versionchanged:: 2.6 | ||||||
|  |       always use absolute imports | ||||||
|  | 
 | ||||||
|    .. index:: single: modules (in module sys) |    .. index:: single: modules (in module sys) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | .. cfunction:: PyObject* PyImport_ImportModuleNoBlock(const char *name) | ||||||
|  | 
 | ||||||
|  |    .. index:: | ||||||
|  |       single: `cfunc:PyImport_ImportModule` | ||||||
|  | 
 | ||||||
|  |    This version of `cfunc:PyImport_ImportModule` does not block. It's intended | ||||||
|  |    to be used in C function which import other modules to execute a function. | ||||||
|  |    The import may block if another thread holds the import lock. The function | ||||||
|  |   `cfunc:PyImport_ImportModuleNoBlock` doesn't block. It first tries to fetch | ||||||
|  |    the module from sys.modules and falls back to `cfunc:PyImport_ImportModule` | ||||||
|  |    unless the the lock is hold. In the latter case the function raises an | ||||||
|  |    ImportError. | ||||||
|  | 
 | ||||||
|  |    .. versionadded:: 2.6 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| .. cfunction:: PyObject* PyImport_ImportModuleEx(char *name, PyObject *globals, PyObject *locals, PyObject *fromlist) | .. cfunction:: PyObject* PyImport_ImportModuleEx(char *name, PyObject *globals, PyObject *locals, PyObject *fromlist) | ||||||
| 
 | 
 | ||||||
|    .. index:: builtin: __import__ |    .. index:: builtin: __import__ | ||||||
|  | @ -218,6 +238,24 @@ Importing Modules | ||||||
|    .. versionchanged:: 2.4 |    .. versionchanged:: 2.4 | ||||||
|       failing imports remove incomplete module objects. |       failing imports remove incomplete module objects. | ||||||
| 
 | 
 | ||||||
|  |    .. versionchanged:: 2.6 | ||||||
|  |       The function is an alias for `cfunc:PyImport_ImportModuleLevel` with | ||||||
|  |       -1 as level, meaning relative import. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | .. cfunction:: PyObject* PyImport_ImportModuleLevel(char *name, PyObject *globals, PyObject *locals, PyObject *fromlist, int level) | ||||||
|  | 
 | ||||||
|  |    Import a module.  This is best described by referring to the built-in Python | ||||||
|  |    function :func:`__import__`, as the standard :func:`__import__` function calls | ||||||
|  |    this function directly. | ||||||
|  | 
 | ||||||
|  |    The return value is a new reference to the imported module or top-level package, | ||||||
|  |    or *NULL* with an exception set on failure.  Like for :func:`__import__`, | ||||||
|  |    the return value when a submodule of a package was requested is normally the | ||||||
|  |    top-level package, unless a non-empty *fromlist* was given. | ||||||
|  | 
 | ||||||
|  |    ..versionadded:: 2.5 | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| .. cfunction:: PyObject* PyImport_Import(PyObject *name) | .. cfunction:: PyObject* PyImport_Import(PyObject *name) | ||||||
| 
 | 
 | ||||||
|  | @ -230,6 +268,9 @@ Importing Modules | ||||||
|    current globals.  This means that the import is done using whatever import hooks |    current globals.  This means that the import is done using whatever import hooks | ||||||
|    are installed in the current environment, e.g. by :mod:`rexec` or :mod:`ihooks`. |    are installed in the current environment, e.g. by :mod:`rexec` or :mod:`ihooks`. | ||||||
| 
 | 
 | ||||||
|  |    .. versionchanged:: 2.6 | ||||||
|  |       always use absolute imports | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| .. cfunction:: PyObject* PyImport_ReloadModule(PyObject *m) | .. cfunction:: PyObject* PyImport_ReloadModule(PyObject *m) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -14,13 +14,10 @@ PyAPI_FUNC(PyObject *) PyImport_ExecCodeModuleEx( | ||||||
| PyAPI_FUNC(PyObject *) PyImport_GetModuleDict(void); | PyAPI_FUNC(PyObject *) PyImport_GetModuleDict(void); | ||||||
| PyAPI_FUNC(PyObject *) PyImport_AddModule(const char *name); | PyAPI_FUNC(PyObject *) PyImport_AddModule(const char *name); | ||||||
| PyAPI_FUNC(PyObject *) PyImport_ImportModule(const char *name); | PyAPI_FUNC(PyObject *) PyImport_ImportModule(const char *name); | ||||||
|  | PyAPI_FUNC(PyObject *) PyImport_ImportModuleNoBlock(const char *); | ||||||
| PyAPI_FUNC(PyObject *) PyImport_ImportModuleLevel(char *name, | PyAPI_FUNC(PyObject *) PyImport_ImportModuleLevel(char *name, | ||||||
| 	PyObject *globals, PyObject *locals, PyObject *fromlist, int level); | 	PyObject *globals, PyObject *locals, PyObject *fromlist, int level); | ||||||
| 
 | 
 | ||||||
| /* For DLL compatibility */ |  | ||||||
| #undef PyImport_ImportModuleEx |  | ||||||
| PyAPI_FUNC(PyObject *) PyImport_ImportModuleEx( |  | ||||||
| 	char *name, PyObject *globals, PyObject *locals, PyObject *fromlist); |  | ||||||
| #define PyImport_ImportModuleEx(n, g, l, f) \ | #define PyImport_ImportModuleEx(n, g, l, f) \ | ||||||
| 	PyImport_ImportModuleLevel(n, g, l, f, -1) | 	PyImport_ImportModuleLevel(n, g, l, f, -1) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -90,7 +90,7 @@ static void **PyCurses_API; | ||||||
| 
 | 
 | ||||||
| #define import_curses() \ | #define import_curses() \ | ||||||
| { \ | { \ | ||||||
|   PyObject *module = PyImport_ImportModule("_curses"); \ |   PyObject *module = PyImport_ImportModuleNoBlock("_curses"); \ | ||||||
|   if (module != NULL) { \ |   if (module != NULL) { \ | ||||||
|     PyObject *module_dict = PyModule_GetDict(module); \ |     PyObject *module_dict = PyModule_GetDict(module); \ | ||||||
|     PyObject *c_api_object = PyDict_GetItemString(module_dict, "_C_API"); \ |     PyObject *c_api_object = PyDict_GetItemString(module_dict, "_C_API"); \ | ||||||
|  |  | ||||||
|  | @ -357,7 +357,7 @@ MacOS_GetErrorString(PyObject *self, PyObject *args) | ||||||
| 		PyObject *m, *rv; | 		PyObject *m, *rv; | ||||||
| 		errors_loaded = 1; | 		errors_loaded = 1; | ||||||
| 		 | 		 | ||||||
| 		m = PyImport_ImportModule("macresource"); | 		m = PyImport_ImportModuleNoBlock("macresource"); | ||||||
| 		if (!m) { | 		if (!m) { | ||||||
| 			if (Py_VerboseFlag) | 			if (Py_VerboseFlag) | ||||||
| 				PyErr_Print(); | 				PyErr_Print(); | ||||||
|  |  | ||||||
							
								
								
									
										36
									
								
								Misc/NEWS
									
										
									
									
									
								
							
							
						
						
									
										36
									
								
								Misc/NEWS
									
										
									
									
									
								
							|  | @ -14,25 +14,10 @@ Core and builtins | ||||||
| 
 | 
 | ||||||
| - Issue #1640: Added math.isinf() and math.isnan() functions. | - Issue #1640: Added math.isinf() and math.isnan() functions. | ||||||
| 
 | 
 | ||||||
| - Issue #1726: Remove Python/atof.c from PCBuild/pythoncore.vcproj |  | ||||||
| 
 |  | ||||||
| - Removed PCbuild8/ directory and added a new build directory for VS 2005 |  | ||||||
|   based on the VS 2008 build directory to PC/VS8.0. The script  |  | ||||||
|   PCbuild/vs8to9.py was added to sync changes from PCbuild to PC/VS8.0. |  | ||||||
| 
 |  | ||||||
| - Moved PCbuild/ directory for VS 2003 to PC/VS7.1 and renamed PCBuild9/ |  | ||||||
|   directory to PCBuild/. |  | ||||||
| 
 |  | ||||||
| - Issue #1629: Renamed Py_Size, Py_Type and Py_Refcnt to Py_SIZE, Py_TYPE |  | ||||||
|   and Py_REFCNT. |  | ||||||
| 
 |  | ||||||
| - Issue #1635: Platform independent creation and representation of NaN | - Issue #1635: Platform independent creation and representation of NaN | ||||||
|   and INF. float("nan"), float("inf") and float("-inf") now work on every |   and INF. float("nan"), float("inf") and float("-inf") now work on every | ||||||
|   platform with IEEE 754 semantics. |   platform with IEEE 754 semantics. | ||||||
| 
 | 
 | ||||||
| - Added case insensitive comparsion methods ``PyOS_stricmp(char*, char*)`` |  | ||||||
|   and ``PyOS_strnicmp(char*, char*, Py_ssize_t)``. |  | ||||||
| 
 |  | ||||||
| - Compiler now generates simpler and faster code for dictionary literals. | - Compiler now generates simpler and faster code for dictionary literals. | ||||||
|   The oparg for BUILD_MAP now indicates an estimated dictionary size. |   The oparg for BUILD_MAP now indicates an estimated dictionary size. | ||||||
|   There is a new opcode, STORE_MAP, for adding entries to the dictionary. |   There is a new opcode, STORE_MAP, for adding entries to the dictionary. | ||||||
|  | @ -1165,6 +1150,15 @@ Tools/Demos | ||||||
| Build | Build | ||||||
| ----- | ----- | ||||||
| 
 | 
 | ||||||
|  | - Issue #1726: Remove Python/atof.c from PCBuild/pythoncore.vcproj | ||||||
|  | 
 | ||||||
|  | - Removed PCbuild8/ directory and added a new build directory for VS 2005 | ||||||
|  |   based on the VS 2008 build directory to PC/VS8.0. The script  | ||||||
|  |   PCbuild/vs8to9.py was added to sync changes from PCbuild to PC/VS8.0. | ||||||
|  | 
 | ||||||
|  | - Moved PCbuild/ directory for VS 2003 to PC/VS7.1 and renamed PCBuild9/ | ||||||
|  |   directory to PCBuild/. | ||||||
|  | 
 | ||||||
| - Bug #1699: Define _BSD_SOURCE only on OpenBSD. | - Bug #1699: Define _BSD_SOURCE only on OpenBSD. | ||||||
| 
 | 
 | ||||||
| - Bug #1608: use -fwrapv when GCC supports it.  This is important, | - Bug #1608: use -fwrapv when GCC supports it.  This is important, | ||||||
|  | @ -1225,6 +1219,18 @@ Build | ||||||
| C API | C API | ||||||
| ----- | ----- | ||||||
| 
 | 
 | ||||||
|  | - Added a new API function ``PyImport_ImportModuleNoBlock``. | ||||||
|  | 
 | ||||||
|  | - ``PyImport_Import`` and ``PyImport_ImportModule`` now always do absolute | ||||||
|  |   imports. In earlier versions they might have used relative imports under | ||||||
|  |   some conditions. | ||||||
|  | 
 | ||||||
|  | - Issue #1629: Renamed Py_Size, Py_Type and Py_Refcnt to Py_SIZE, Py_TYPE | ||||||
|  |   and Py_REFCNT. | ||||||
|  | 
 | ||||||
|  | - Added case insensitive comparsion methods ``PyOS_stricmp(char*, char*)`` | ||||||
|  |   and ``PyOS_strnicmp(char*, char*, Py_ssize_t)``. | ||||||
|  | 
 | ||||||
| - Bug #1542693: remove semi-colon at end of PyImport_ImportModuleEx macro | - Bug #1542693: remove semi-colon at end of PyImport_ImportModuleEx macro | ||||||
|   so it can be used as an expression. |   so it can be used as an expression. | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -370,7 +370,7 @@ long Call_GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) | ||||||
| 	if (context == NULL) | 	if (context == NULL) | ||||||
| 		context = PyString_FromString("_ctypes.DllGetClassObject"); | 		context = PyString_FromString("_ctypes.DllGetClassObject"); | ||||||
| 
 | 
 | ||||||
| 	mod = PyImport_ImportModule("ctypes"); | 	mod = PyImport_ImportModuleNoBlock("ctypes"); | ||||||
| 	if (!mod) { | 	if (!mod) { | ||||||
| 		PyErr_WriteUnraisable(context ? context : Py_None); | 		PyErr_WriteUnraisable(context ? context : Py_None); | ||||||
| 		/* There has been a warning before about this already */ | 		/* There has been a warning before about this already */ | ||||||
|  | @ -449,7 +449,7 @@ long Call_CanUnloadNow(void) | ||||||
| 	if (context == NULL) | 	if (context == NULL) | ||||||
| 		context = PyString_FromString("_ctypes.DllCanUnloadNow"); | 		context = PyString_FromString("_ctypes.DllCanUnloadNow"); | ||||||
| 
 | 
 | ||||||
| 	mod = PyImport_ImportModule("ctypes"); | 	mod = PyImport_ImportModuleNoBlock("ctypes"); | ||||||
| 	if (!mod) { | 	if (!mod) { | ||||||
| /*		OutputDebugString("Could not import ctypes"); */ | /*		OutputDebugString("Could not import ctypes"); */ | ||||||
| 		/* We assume that this error can only occur when shutting
 | 		/* We assume that this error can only occur when shutting
 | ||||||
|  |  | ||||||
|  | @ -2255,7 +2255,7 @@ static int | ||||||
| update_lines_cols(void) | update_lines_cols(void) | ||||||
| { | { | ||||||
|   PyObject *o; |   PyObject *o; | ||||||
|   PyObject *m = PyImport_ImportModule("curses"); |   PyObject *m = PyImport_ImportModuleNoBlock("curses"); | ||||||
| 
 | 
 | ||||||
|   if (!m) |   if (!m) | ||||||
|     return 0; |     return 0; | ||||||
|  |  | ||||||
|  | @ -245,7 +245,7 @@ getmultibytecodec(void) | ||||||
| 	static PyObject *cofunc = NULL; | 	static PyObject *cofunc = NULL; | ||||||
| 
 | 
 | ||||||
| 	if (cofunc == NULL) { | 	if (cofunc == NULL) { | ||||||
| 		PyObject *mod = PyImport_ImportModule("_multibytecodec"); | 		PyObject *mod = PyImport_ImportModuleNoBlock("_multibytecodec"); | ||||||
| 		if (mod == NULL) | 		if (mod == NULL) | ||||||
| 			return NULL; | 			return NULL; | ||||||
| 		cofunc = PyObject_GetAttrString(mod, "__create_codec"); | 		cofunc = PyObject_GetAttrString(mod, "__create_codec"); | ||||||
|  |  | ||||||
|  | @ -1305,7 +1305,7 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple, | ||||||
| 	if (_PyString_Resize(&newfmt, usednew) < 0) | 	if (_PyString_Resize(&newfmt, usednew) < 0) | ||||||
| 		goto Done; | 		goto Done; | ||||||
| 	{ | 	{ | ||||||
| 		PyObject *time = PyImport_ImportModule("time"); | 		PyObject *time = PyImport_ImportModuleNoBlock("time"); | ||||||
| 		if (time == NULL) | 		if (time == NULL) | ||||||
| 			goto Done; | 			goto Done; | ||||||
| 		result = PyObject_CallMethod(time, "strftime", "OO", | 		result = PyObject_CallMethod(time, "strftime", "OO", | ||||||
|  | @ -1353,7 +1353,7 @@ static PyObject * | ||||||
| time_time(void) | time_time(void) | ||||||
| { | { | ||||||
| 	PyObject *result = NULL; | 	PyObject *result = NULL; | ||||||
| 	PyObject *time = PyImport_ImportModule("time"); | 	PyObject *time = PyImport_ImportModuleNoBlock("time"); | ||||||
| 
 | 
 | ||||||
| 	if (time != NULL) { | 	if (time != NULL) { | ||||||
| 		result = PyObject_CallMethod(time, "time", "()"); | 		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) | ||||||
| 	PyObject *time; | 	PyObject *time; | ||||||
| 	PyObject *result = NULL; | 	PyObject *result = NULL; | ||||||
| 
 | 
 | ||||||
| 	time = PyImport_ImportModule("time"); | 	time = PyImport_ImportModuleNoBlock("time"); | ||||||
| 	if (time != NULL) { | 	if (time != NULL) { | ||||||
| 		result = PyObject_CallMethod(time, "struct_time", | 		result = PyObject_CallMethod(time, "struct_time", | ||||||
| 					     "((iiiiiiiii))", | 					     "((iiiiiiiii))", | ||||||
|  | @ -3827,7 +3827,7 @@ datetime_strptime(PyObject *cls, PyObject *args) | ||||||
| 	if (!PyArg_ParseTuple(args, "ss:strptime", &string, &format)) | 	if (!PyArg_ParseTuple(args, "ss:strptime", &string, &format)) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 
 | 
 | ||||||
| 	if ((module = PyImport_ImportModule("time")) == NULL) | 	if ((module = PyImport_ImportModuleNoBlock("time")) == NULL) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	obj = PyObject_CallMethod(module, "strptime", "ss", string, format); | 	obj = PyObject_CallMethod(module, "strptime", "ss", string, format); | ||||||
| 	Py_DECREF(module); | 	Py_DECREF(module); | ||||||
|  |  | ||||||
|  | @ -1236,7 +1236,7 @@ initgc(void) | ||||||
| 	 * the import and triggers an assertion. | 	 * the import and triggers an assertion. | ||||||
| 	 */ | 	 */ | ||||||
| 	if (tmod == NULL) { | 	if (tmod == NULL) { | ||||||
| 		tmod = PyImport_ImportModule("time"); | 		tmod = PyImport_ImportModuleNoBlock("time"); | ||||||
| 		if (tmod == NULL) | 		if (tmod == NULL) | ||||||
| 			PyErr_Clear(); | 			PyErr_Clear(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -3269,7 +3269,7 @@ initparser(void) | ||||||
|      * If this fails, the import of this module will fail because an |      * If this fails, the import of this module will fail because an | ||||||
|      * exception will be raised here; should we clear the exception? |      * exception will be raised here; should we clear the exception? | ||||||
|      */ |      */ | ||||||
|     copyreg = PyImport_ImportModule("copy_reg"); |     copyreg = PyImport_ImportModuleNoBlock("copy_reg"); | ||||||
|     if (copyreg != NULL) { |     if (copyreg != NULL) { | ||||||
|         PyObject *func, *pickler; |         PyObject *func, *pickler; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -5651,7 +5651,7 @@ wait_helper(int pid, int status, struct rusage *ru) | ||||||
| 		return posix_error(); | 		return posix_error(); | ||||||
| 
 | 
 | ||||||
| 	if (struct_rusage == NULL) { | 	if (struct_rusage == NULL) { | ||||||
| 		PyObject *m = PyImport_ImportModule("resource"); | 		PyObject *m = PyImport_ImportModuleNoBlock("resource"); | ||||||
| 		if (m == NULL) | 		if (m == NULL) | ||||||
| 			return NULL; | 			return NULL; | ||||||
| 		struct_rusage = PyObject_GetAttrString(m, "struct_rusage"); | 		struct_rusage = PyObject_GetAttrString(m, "struct_rusage"); | ||||||
|  |  | ||||||
|  | @ -222,7 +222,7 @@ int PySocketModule_ImportModuleAndAPI(void) | ||||||
| 	void *api; | 	void *api; | ||||||
| 
 | 
 | ||||||
| 	DPRINTF("Importing the %s C API...\n", apimodule); | 	DPRINTF("Importing the %s C API...\n", apimodule); | ||||||
| 	mod = PyImport_ImportModule(apimodule); | 	mod = PyImport_ImportModuleNoBlock(apimodule); | ||||||
| 	if (mod == NULL) | 	if (mod == NULL) | ||||||
| 		goto onError; | 		goto onError; | ||||||
| 	DPRINTF(" %s package found\n", apimodule); | 	DPRINTF(" %s package found\n", apimodule); | ||||||
|  |  | ||||||
|  | @ -515,7 +515,7 @@ is not present, current time as returned by localtime() is used."); | ||||||
| static PyObject * | static PyObject * | ||||||
| time_strptime(PyObject *self, PyObject *args) | time_strptime(PyObject *self, PyObject *args) | ||||||
| { | { | ||||||
|     PyObject *strptime_module = PyImport_ImportModule("_strptime"); |     PyObject *strptime_module = PyImport_ImportModuleNoBlock("_strptime"); | ||||||
|     PyObject *strptime_result; |     PyObject *strptime_result; | ||||||
| 
 | 
 | ||||||
|     if (!strptime_module) |     if (!strptime_module) | ||||||
|  | @ -627,7 +627,7 @@ time_tzset(PyObject *self, PyObject *unused) | ||||||
| { | { | ||||||
| 	PyObject* m; | 	PyObject* m; | ||||||
| 
 | 
 | ||||||
| 	m = PyImport_ImportModule("time"); | 	m = PyImport_ImportModuleNoBlock("time"); | ||||||
| 	if (m == NULL) { | 	if (m == NULL) { | ||||||
| 	    return NULL; | 	    return NULL; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -776,7 +776,7 @@ get_decompress_func(void) | ||||||
| 			   let's avoid a stack overflow. */ | 			   let's avoid a stack overflow. */ | ||||||
| 			return NULL; | 			return NULL; | ||||||
| 		importing_zlib = 1; | 		importing_zlib = 1; | ||||||
| 		zlib = PyImport_ImportModule("zlib");	/* import zlib */ | 		zlib = PyImport_ImportModuleNoBlock("zlib"); | ||||||
| 		importing_zlib = 0; | 		importing_zlib = 0; | ||||||
| 		if (zlib != NULL) { | 		if (zlib != NULL) { | ||||||
| 			decompress = PyObject_GetAttrString(zlib, | 			decompress = PyObject_GetAttrString(zlib, | ||||||
|  |  | ||||||
|  | @ -2216,7 +2216,7 @@ PyObject *PyUnicode_DecodeUnicodeEscape(const char *s, | ||||||
|             if (ucnhash_CAPI == NULL) { |             if (ucnhash_CAPI == NULL) { | ||||||
|                 /* load the unicode data module */ |                 /* load the unicode data module */ | ||||||
|                 PyObject *m, *api; |                 PyObject *m, *api; | ||||||
|                 m = PyImport_ImportModule("unicodedata"); |                 m = PyImport_ImportModuleNoBlock("unicodedata"); | ||||||
|                 if (m == NULL) |                 if (m == NULL) | ||||||
|                     goto ucnhashError; |                     goto ucnhashError; | ||||||
|                 api = PyObject_GetAttrString(m, "ucnhash_CAPI"); |                 api = PyObject_GetAttrString(m, "ucnhash_CAPI"); | ||||||
|  |  | ||||||
|  | @ -690,7 +690,7 @@ PyErr_WarnExplicit(PyObject *category, const char *message, | ||||||
| { | { | ||||||
| 	PyObject *mod, *dict, *func = NULL; | 	PyObject *mod, *dict, *func = NULL; | ||||||
| 
 | 
 | ||||||
| 	mod = PyImport_ImportModule("warnings"); | 	mod = PyImport_ImportModuleNoBlock("warnings"); | ||||||
| 	if (mod != NULL) { | 	if (mod != NULL) { | ||||||
| 		dict = PyModule_GetDict(mod); | 		dict = PyModule_GetDict(mod); | ||||||
| 		func = PyDict_GetItemString(dict, "warn_explicit"); | 		func = PyDict_GetItemString(dict, "warn_explicit"); | ||||||
|  |  | ||||||
|  | @ -1985,6 +1985,53 @@ PyImport_ImportModule(const char *name) | ||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* Import a module without blocking
 | ||||||
|  |  * | ||||||
|  |  * At first it tries to fetch the module from sys.modules. If the module was | ||||||
|  |  * never loaded before it loads it with PyImport_ImportModule() unless another | ||||||
|  |  * thread holds the import lock. In the latter case the function raises an | ||||||
|  |  * ImportError instead of blocking. | ||||||
|  |  * | ||||||
|  |  * Returns the module object with incremented ref count. | ||||||
|  |  */ | ||||||
|  | PyObject * | ||||||
|  | PyImport_ImportModuleNoBlock(const char *name) | ||||||
|  | { | ||||||
|  | 	PyObject *result; | ||||||
|  | 	PyObject *modules; | ||||||
|  | 	long me; | ||||||
|  | 
 | ||||||
|  | 	/* Try to get the module from sys.modules[name] */ | ||||||
|  | 	modules = PyImport_GetModuleDict(); | ||||||
|  | 	if (modules == NULL) | ||||||
|  | 		return NULL; | ||||||
|  | 
 | ||||||
|  | 	result = PyDict_GetItemString(modules, name); | ||||||
|  | 	if (result != NULL) { | ||||||
|  | 		Py_INCREF(result); | ||||||
|  | 		return result; | ||||||
|  | 	} | ||||||
|  | 	else { | ||||||
|  | 		PyErr_Clear(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* check the import lock
 | ||||||
|  | 	 * me might be -1 but I ignore the error here, the lock function | ||||||
|  | 	 * takes care of the problem */ | ||||||
|  | 	me = PyThread_get_thread_ident(); | ||||||
|  | 	if (import_lock_thread == -1 || import_lock_thread == me) { | ||||||
|  | 		/* no thread or me is holding the lock */ | ||||||
|  | 		return PyImport_ImportModule(name); | ||||||
|  | 	} | ||||||
|  | 	else { | ||||||
|  | 		PyErr_Format(PyExc_ImportError, | ||||||
|  | 			     "Failed to import %.200s because the import lock" | ||||||
|  | 			     "is held by another thread.", | ||||||
|  | 			     name); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /* Forward declarations for helper routines */ | /* Forward declarations for helper routines */ | ||||||
| static PyObject *get_parent(PyObject *globals, char *buf, | static PyObject *get_parent(PyObject *globals, char *buf, | ||||||
| 			    Py_ssize_t *p_buflen, int level); | 			    Py_ssize_t *p_buflen, int level); | ||||||
|  | @ -2054,26 +2101,6 @@ import_module_level(char *name, PyObject *globals, PyObject *locals, | ||||||
| 	return tail; | 	return tail; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* For DLL compatibility */ |  | ||||||
| #undef PyImport_ImportModuleEx |  | ||||||
| PyObject * |  | ||||||
| PyImport_ImportModuleEx(char *name, PyObject *globals, PyObject *locals, |  | ||||||
| 			PyObject *fromlist) |  | ||||||
| { |  | ||||||
| 	PyObject *result; |  | ||||||
| 	lock_import(); |  | ||||||
| 	result = import_module_level(name, globals, locals, fromlist, -1); |  | ||||||
| 	if (unlock_import() < 0) { |  | ||||||
| 		Py_XDECREF(result); |  | ||||||
| 		PyErr_SetString(PyExc_RuntimeError, |  | ||||||
| 				"not holding the import lock"); |  | ||||||
| 		return NULL; |  | ||||||
| 	} |  | ||||||
| 	return result; |  | ||||||
| } |  | ||||||
| #define PyImport_ImportModuleEx(n, g, l, f) \ |  | ||||||
| 	PyImport_ImportModuleLevel(n, g, l, f, -1); |  | ||||||
| 
 |  | ||||||
| PyObject * | PyObject * | ||||||
| PyImport_ImportModuleLevel(char *name, PyObject *globals, PyObject *locals, | PyImport_ImportModuleLevel(char *name, PyObject *globals, PyObject *locals, | ||||||
| 			 PyObject *fromlist, int level) | 			 PyObject *fromlist, int level) | ||||||
|  | @ -2646,9 +2673,10 @@ PyImport_Import(PyObject *module_name) | ||||||
| 	if (import == NULL) | 	if (import == NULL) | ||||||
| 		goto err; | 		goto err; | ||||||
| 
 | 
 | ||||||
| 	/* Call the __import__ function with the proper argument list */ | 	/* Call the __import__ function with the proper argument list
 | ||||||
| 	r = PyObject_CallFunctionObjArgs(import, module_name, globals, | 	 * Always use absolute import here. */ | ||||||
| 					 globals, silly_list, NULL); | 	r = PyObject_CallFunction(import, "OOOOi", module_name, globals, | ||||||
|  | 				  globals, silly_list, 0, NULL); | ||||||
| 
 | 
 | ||||||
|   err: |   err: | ||||||
| 	Py_XDECREF(globals); | 	Py_XDECREF(globals); | ||||||
|  |  | ||||||
|  | @ -36,7 +36,7 @@ PyMac_StrError(int err) | ||||||
| 	PyObject *m; | 	PyObject *m; | ||||||
| 	PyObject *rv; | 	PyObject *rv; | ||||||
| 
 | 
 | ||||||
| 	m = PyImport_ImportModule("MacOS"); | 	m = PyImport_ImportModuleNoBlock("MacOS"); | ||||||
| 	if (!m) { | 	if (!m) { | ||||||
| 		if (Py_VerboseFlag) | 		if (Py_VerboseFlag) | ||||||
| 			PyErr_Print(); | 			PyErr_Print(); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Christian Heimes
						Christian Heimes