From c374e0aff571df7366818e9421473314bb52ab4c Mon Sep 17 00:00:00 2001 From: Joannah nanjekye Date: Wed, 31 Jul 2019 12:46:09 -0300 Subject: [PATCH 01/10] PyImport_GetModule() can return partially-initialized module --- Python/import.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/Python/import.c b/Python/import.c index 9f5ec284ae15120..0a94d5c6eb37ebe 100644 --- a/Python/import.c +++ b/Python/import.c @@ -390,8 +390,33 @@ import_get_module(PyThreadState *tstate, PyObject *name) PyObject * PyImport_GetModule(PyObject *name) { - PyThreadState *tstate = _PyThreadState_GET(); - return import_get_module(tstate, name); + PyThreadState *tstate = _PyThreadState_GET(); + PyObject *mod = NULL; + PyInterpreterState *interp = tstate->interp; + + mod = import_get_module(tstate, name); + if (mod != NULL && mod != Py_None) { + _Py_IDENTIFIER(__spec__); + _Py_IDENTIFIER(_lock_unlock_module); + PyObject *spec; + + /* Optimization: only call _bootstrap._lock_unlock_module() if + __spec__._initializing is true. + NOTE: because of this, initializing must be set *before* + stuffing the new module in sys.modules. + */ + spec = _PyObject_GetAttrId(mod, &PyId___spec__); + if (_PyModuleSpec_IsInitializing(spec)) { + PyObject *value = _PyObject_CallMethodIdOneArg( + interp->importlib, &PyId__lock_unlock_module, name); + if (value == NULL) { + Py_DECREF(spec); + } + Py_DECREF(value); + } + Py_XDECREF(spec); + } + return mod; } From 01fe07951ecb6ee94fd113ae732f3cd2662a6967 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Wed, 31 Jul 2019 15:52:58 +0000 Subject: [PATCH 02/10] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NEWS.d/next/Library/2019-07-31-15-52-51.bpo-35943.-KswoB.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2019-07-31-15-52-51.bpo-35943.-KswoB.rst diff --git a/Misc/NEWS.d/next/Library/2019-07-31-15-52-51.bpo-35943.-KswoB.rst b/Misc/NEWS.d/next/Library/2019-07-31-15-52-51.bpo-35943.-KswoB.rst new file mode 100644 index 000000000000000..5762c974504cad1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-07-31-15-52-51.bpo-35943.-KswoB.rst @@ -0,0 +1 @@ +Added optimization to prevent `PyImport_GetModule()` from returning partially-initialized module. \ No newline at end of file From f2be697ab3179bcd934a1d62d9580ba259de6fc0 Mon Sep 17 00:00:00 2001 From: Joannah nanjekye Date: Thu, 1 Aug 2019 13:35:59 -0300 Subject: [PATCH 03/10] Isolate duplicate code in a function --- Python/import.c | 201 ++++++++++++++++++++++++------------------------ 1 file changed, 101 insertions(+), 100 deletions(-) diff --git a/Python/import.c b/Python/import.c index 0a94d5c6eb37ebe..eea53131ad5cea3 100644 --- a/Python/import.c +++ b/Python/import.c @@ -386,37 +386,115 @@ import_get_module(PyThreadState *tstate, PyObject *name) return m; } +static int +import_ensure_initialized(PyThreadState *tstate, PyObject *mod, PyObject *name) +{ + PyInterpreterState *interp = tstate->interp; + PyObject *spec; + PyObject *value = NULL; + + _Py_IDENTIFIER(__spec__); + _Py_IDENTIFIER(_lock_unlock_module); + + /* Optimization: only call _bootstrap._lock_unlock_module() if + __spec__._initializing is true. + NOTE: because of this, initializing must be set *before* + stuffing the new module in sys.modules. + */ + spec = _PyObject_GetAttrId(mod, &PyId___spec__); + if (_PyModuleSpec_IsInitializing(spec)) { + value = _PyObject_CallMethodIdOneArg( + interp->importlib, &PyId__lock_unlock_module, name); + if (value == NULL) { + Py_DECREF(spec); + return -1; + } + else { + return 0; + } + Py_DECREF(value); + } + Py_XDECREF(spec); + return 0; +} + + +/* Remove importlib frames from the traceback, + * except in Verbose mode. */ +static void +remove_importlib_frames(PyThreadState *tstate) +{ + const char *importlib_filename = ""; + const char *external_filename = ""; + const char *remove_frames = "_call_with_frames_removed"; + int always_trim = 0; + int in_importlib = 0; + PyObject *exception, *value, *base_tb, *tb; + PyObject **prev_link, **outer_link = NULL; + + /* Synopsis: if it's an ImportError, we trim all importlib chunks + from the traceback. We always trim chunks + which end with a call to "_call_with_frames_removed". */ + + _PyErr_Fetch(tstate, &exception, &value, &base_tb); + if (!exception || tstate->interp->config.verbose) { + goto done; + } + + if (PyType_IsSubtype((PyTypeObject *) exception, + (PyTypeObject *) PyExc_ImportError)) + always_trim = 1; + + prev_link = &base_tb; + tb = base_tb; + while (tb != NULL) { + PyTracebackObject *traceback = (PyTracebackObject *)tb; + PyObject *next = (PyObject *) traceback->tb_next; + PyFrameObject *frame = traceback->tb_frame; + PyCodeObject *code = frame->f_code; + int now_in_importlib; + + assert(PyTraceBack_Check(tb)); + now_in_importlib = _PyUnicode_EqualToASCIIString(code->co_filename, importlib_filename) || + _PyUnicode_EqualToASCIIString(code->co_filename, external_filename); + if (now_in_importlib && !in_importlib) { + /* This is the link to this chunk of importlib tracebacks */ + outer_link = prev_link; + } + in_importlib = now_in_importlib; + + if (in_importlib && + (always_trim || + _PyUnicode_EqualToASCIIString(code->co_name, remove_frames))) { + Py_XINCREF(next); + Py_XSETREF(*outer_link, next); + prev_link = outer_link; + } + else { + prev_link = (PyObject **) &traceback->tb_next; + } + tb = next; + } +done: + _PyErr_Restore(tstate, exception, value, base_tb); +} + PyObject * PyImport_GetModule(PyObject *name) { PyThreadState *tstate = _PyThreadState_GET(); PyObject *mod = NULL; - PyInterpreterState *interp = tstate->interp; mod = import_get_module(tstate, name); if (mod != NULL && mod != Py_None) { - _Py_IDENTIFIER(__spec__); - _Py_IDENTIFIER(_lock_unlock_module); - PyObject *spec; - - /* Optimization: only call _bootstrap._lock_unlock_module() if - __spec__._initializing is true. - NOTE: because of this, initializing must be set *before* - stuffing the new module in sys.modules. - */ - spec = _PyObject_GetAttrId(mod, &PyId___spec__); - if (_PyModuleSpec_IsInitializing(spec)) { - PyObject *value = _PyObject_CallMethodIdOneArg( - interp->importlib, &PyId__lock_unlock_module, name); - if (value == NULL) { - Py_DECREF(spec); - } - Py_DECREF(value); + int value = import_ensure_initialized(tstate, mod, name); + if (value == -1) { + remove_importlib_frames(tstate); + return NULL; } - Py_XDECREF(spec); } - return mod; + return mod; } @@ -1502,67 +1580,6 @@ PyImport_ImportModuleNoBlock(const char *name) } -/* Remove importlib frames from the traceback, - * except in Verbose mode. */ -static void -remove_importlib_frames(PyThreadState *tstate) -{ - const char *importlib_filename = ""; - const char *external_filename = ""; - const char *remove_frames = "_call_with_frames_removed"; - int always_trim = 0; - int in_importlib = 0; - PyObject *exception, *value, *base_tb, *tb; - PyObject **prev_link, **outer_link = NULL; - - /* Synopsis: if it's an ImportError, we trim all importlib chunks - from the traceback. We always trim chunks - which end with a call to "_call_with_frames_removed". */ - - _PyErr_Fetch(tstate, &exception, &value, &base_tb); - if (!exception || tstate->interp->config.verbose) { - goto done; - } - - if (PyType_IsSubtype((PyTypeObject *) exception, - (PyTypeObject *) PyExc_ImportError)) - always_trim = 1; - - prev_link = &base_tb; - tb = base_tb; - while (tb != NULL) { - PyTracebackObject *traceback = (PyTracebackObject *)tb; - PyObject *next = (PyObject *) traceback->tb_next; - PyFrameObject *frame = traceback->tb_frame; - PyCodeObject *code = frame->f_code; - int now_in_importlib; - - assert(PyTraceBack_Check(tb)); - now_in_importlib = _PyUnicode_EqualToASCIIString(code->co_filename, importlib_filename) || - _PyUnicode_EqualToASCIIString(code->co_filename, external_filename); - if (now_in_importlib && !in_importlib) { - /* This is the link to this chunk of importlib tracebacks */ - outer_link = prev_link; - } - in_importlib = now_in_importlib; - - if (in_importlib && - (always_trim || - _PyUnicode_EqualToASCIIString(code->co_name, remove_frames))) { - Py_XINCREF(next); - Py_XSETREF(*outer_link, next); - prev_link = outer_link; - } - else { - prev_link = (PyObject **) &traceback->tb_next; - } - tb = next; - } -done: - _PyErr_Restore(tstate, exception, value, base_tb); -} - - static PyObject * resolve_name(PyThreadState *tstate, PyObject *name, PyObject *globals, int level) { @@ -1840,26 +1857,10 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, } if (mod != NULL && mod != Py_None) { - _Py_IDENTIFIER(__spec__); - _Py_IDENTIFIER(_lock_unlock_module); - PyObject *spec; - - /* Optimization: only call _bootstrap._lock_unlock_module() if - __spec__._initializing is true. - NOTE: because of this, initializing must be set *before* - stuffing the new module in sys.modules. - */ - spec = _PyObject_GetAttrId(mod, &PyId___spec__); - if (_PyModuleSpec_IsInitializing(spec)) { - PyObject *value = _PyObject_CallMethodIdOneArg( - interp->importlib, &PyId__lock_unlock_module, abs_name); - if (value == NULL) { - Py_DECREF(spec); - goto error; - } - Py_DECREF(value); + int value = import_ensure_initialized(tstate, mod, abs_name); + if (value == -1) { + goto error; } - Py_XDECREF(spec); } else { Py_XDECREF(mod); From 09258125d4075dcfea5e4ceb10d8390c0b42ecac Mon Sep 17 00:00:00 2001 From: Joannah Nanjekye Date: Fri, 2 Aug 2019 13:45:02 +0000 Subject: [PATCH 04/10] ensure any module returned is initialized --- .../2019-07-31-15-52-51.bpo-35943.-KswoB.rst | 2 +- Python/import.c | 168 +++++++++--------- 2 files changed, 83 insertions(+), 87 deletions(-) diff --git a/Misc/NEWS.d/next/Library/2019-07-31-15-52-51.bpo-35943.-KswoB.rst b/Misc/NEWS.d/next/Library/2019-07-31-15-52-51.bpo-35943.-KswoB.rst index 5762c974504cad1..e70737974d6d696 100644 --- a/Misc/NEWS.d/next/Library/2019-07-31-15-52-51.bpo-35943.-KswoB.rst +++ b/Misc/NEWS.d/next/Library/2019-07-31-15-52-51.bpo-35943.-KswoB.rst @@ -1 +1 @@ -Added optimization to prevent `PyImport_GetModule()` from returning partially-initialized module. \ No newline at end of file +The function :c:func:`PyImport_GetModule` now ensures any module it returns is fully initialized. \ No newline at end of file diff --git a/Python/import.c b/Python/import.c index eea53131ad5cea3..474137c94e7419a 100644 --- a/Python/import.c +++ b/Python/import.c @@ -386,12 +386,12 @@ import_get_module(PyThreadState *tstate, PyObject *name) return m; } + static int import_ensure_initialized(PyThreadState *tstate, PyObject *mod, PyObject *name) { PyInterpreterState *interp = tstate->interp; PyObject *spec; - PyObject *value = NULL; _Py_IDENTIFIER(__spec__); _Py_IDENTIFIER(_lock_unlock_module); @@ -403,15 +403,12 @@ import_ensure_initialized(PyThreadState *tstate, PyObject *mod, PyObject *name) */ spec = _PyObject_GetAttrId(mod, &PyId___spec__); if (_PyModuleSpec_IsInitializing(spec)) { - value = _PyObject_CallMethodIdOneArg( + PyObject *value = _PyObject_CallMethodIdOneArg( interp->importlib, &PyId__lock_unlock_module, name); if (value == NULL) { Py_DECREF(spec); return -1; } - else { - return 0; - } Py_DECREF(value); } Py_XDECREF(spec); @@ -419,85 +416,6 @@ import_ensure_initialized(PyThreadState *tstate, PyObject *mod, PyObject *name) } -/* Remove importlib frames from the traceback, - * except in Verbose mode. */ -static void -remove_importlib_frames(PyThreadState *tstate) -{ - const char *importlib_filename = ""; - const char *external_filename = ""; - const char *remove_frames = "_call_with_frames_removed"; - int always_trim = 0; - int in_importlib = 0; - PyObject *exception, *value, *base_tb, *tb; - PyObject **prev_link, **outer_link = NULL; - - /* Synopsis: if it's an ImportError, we trim all importlib chunks - from the traceback. We always trim chunks - which end with a call to "_call_with_frames_removed". */ - - _PyErr_Fetch(tstate, &exception, &value, &base_tb); - if (!exception || tstate->interp->config.verbose) { - goto done; - } - - if (PyType_IsSubtype((PyTypeObject *) exception, - (PyTypeObject *) PyExc_ImportError)) - always_trim = 1; - - prev_link = &base_tb; - tb = base_tb; - while (tb != NULL) { - PyTracebackObject *traceback = (PyTracebackObject *)tb; - PyObject *next = (PyObject *) traceback->tb_next; - PyFrameObject *frame = traceback->tb_frame; - PyCodeObject *code = frame->f_code; - int now_in_importlib; - - assert(PyTraceBack_Check(tb)); - now_in_importlib = _PyUnicode_EqualToASCIIString(code->co_filename, importlib_filename) || - _PyUnicode_EqualToASCIIString(code->co_filename, external_filename); - if (now_in_importlib && !in_importlib) { - /* This is the link to this chunk of importlib tracebacks */ - outer_link = prev_link; - } - in_importlib = now_in_importlib; - - if (in_importlib && - (always_trim || - _PyUnicode_EqualToASCIIString(code->co_name, remove_frames))) { - Py_XINCREF(next); - Py_XSETREF(*outer_link, next); - prev_link = outer_link; - } - else { - prev_link = (PyObject **) &traceback->tb_next; - } - tb = next; - } -done: - _PyErr_Restore(tstate, exception, value, base_tb); -} - - -PyObject * -PyImport_GetModule(PyObject *name) -{ - PyThreadState *tstate = _PyThreadState_GET(); - PyObject *mod = NULL; - - mod = import_get_module(tstate, name); - if (mod != NULL && mod != Py_None) { - int value = import_ensure_initialized(tstate, mod, name); - if (value == -1) { - remove_importlib_frames(tstate); - return NULL; - } - } - return mod; -} - - /* List of names to clear in sys */ static const char * const sys_deletes[] = { "path", "argv", "ps1", "ps2", @@ -1564,6 +1482,7 @@ PyImport_ImportModule(const char *name) return result; } + /* Import a module without blocking * * At first it tries to fetch the module from sys.modules. If the module was @@ -1580,6 +1499,67 @@ PyImport_ImportModuleNoBlock(const char *name) } +/* Remove importlib frames from the traceback, + * except in Verbose mode. */ +static void +remove_importlib_frames(PyThreadState *tstate) +{ + const char *importlib_filename = ""; + const char *external_filename = ""; + const char *remove_frames = "_call_with_frames_removed"; + int always_trim = 0; + int in_importlib = 0; + PyObject *exception, *value, *base_tb, *tb; + PyObject **prev_link, **outer_link = NULL; + + /* Synopsis: if it's an ImportError, we trim all importlib chunks + from the traceback. We always trim chunks + which end with a call to "_call_with_frames_removed". */ + + _PyErr_Fetch(tstate, &exception, &value, &base_tb); + if (!exception || tstate->interp->config.verbose) { + goto done; + } + + if (PyType_IsSubtype((PyTypeObject *) exception, + (PyTypeObject *) PyExc_ImportError)) + always_trim = 1; + + prev_link = &base_tb; + tb = base_tb; + while (tb != NULL) { + PyTracebackObject *traceback = (PyTracebackObject *)tb; + PyObject *next = (PyObject *) traceback->tb_next; + PyFrameObject *frame = traceback->tb_frame; + PyCodeObject *code = frame->f_code; + int now_in_importlib; + + assert(PyTraceBack_Check(tb)); + now_in_importlib = _PyUnicode_EqualToASCIIString(code->co_filename, importlib_filename) || + _PyUnicode_EqualToASCIIString(code->co_filename, external_filename); + if (now_in_importlib && !in_importlib) { + /* This is the link to this chunk of importlib tracebacks */ + outer_link = prev_link; + } + in_importlib = now_in_importlib; + + if (in_importlib && + (always_trim || + _PyUnicode_EqualToASCIIString(code->co_name, remove_frames))) { + Py_XINCREF(next); + Py_XSETREF(*outer_link, next); + prev_link = outer_link; + } + else { + prev_link = (PyObject **) &traceback->tb_next; + } + tb = next; + } +done: + _PyErr_Restore(tstate, exception, value, base_tb); +} + + static PyObject * resolve_name(PyThreadState *tstate, PyObject *name, PyObject *globals, int level) { @@ -1802,6 +1782,23 @@ import_find_and_load(PyThreadState *tstate, PyObject *abs_name) return mod; } +PyObject * +PyImport_GetModule(PyObject *name) +{ + PyThreadState *tstate = _PyThreadState_GET(); + PyObject *mod = NULL; + + mod = import_get_module(tstate, name); + if (mod != NULL && mod != Py_None) { + if (import_ensure_initialized(tstate, mod, name) < 0) { + Py_XDECREF(mod); + remove_importlib_frames(tstate); + return NULL; + } + } + return mod; +} + PyObject * PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, PyObject *locals, PyObject *fromlist, @@ -1857,8 +1854,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals, } if (mod != NULL && mod != Py_None) { - int value = import_ensure_initialized(tstate, mod, abs_name); - if (value == -1) { + if (import_ensure_initialized(tstate, mod, name) < 0) { goto error; } } From 57a6231816ec337fb56784a57b83d19de3f1eb44 Mon Sep 17 00:00:00 2001 From: Joannah Nanjekye Date: Fri, 2 Aug 2019 20:14:36 +0000 Subject: [PATCH 05/10] change to Py_DECREF and fix doc --- .../2019-07-31-15-52-51.bpo-35943.-KswoB.rst | 3 ++- Python/import.c | 24 +++++++++---------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/Misc/NEWS.d/next/Library/2019-07-31-15-52-51.bpo-35943.-KswoB.rst b/Misc/NEWS.d/next/Library/2019-07-31-15-52-51.bpo-35943.-KswoB.rst index e70737974d6d696..3877ba839551579 100644 --- a/Misc/NEWS.d/next/Library/2019-07-31-15-52-51.bpo-35943.-KswoB.rst +++ b/Misc/NEWS.d/next/Library/2019-07-31-15-52-51.bpo-35943.-KswoB.rst @@ -1 +1,2 @@ -The function :c:func:`PyImport_GetModule` now ensures any module it returns is fully initialized. \ No newline at end of file +The function :c:func:`PyImport_GetModule` now ensures any module it returns is fully initialized. +Patch by Joannah Nanjekye \ No newline at end of file diff --git a/Python/import.c b/Python/import.c index 474137c94e7419a..d6439f07b2bfe0f 100644 --- a/Python/import.c +++ b/Python/import.c @@ -397,9 +397,9 @@ import_ensure_initialized(PyThreadState *tstate, PyObject *mod, PyObject *name) _Py_IDENTIFIER(_lock_unlock_module); /* Optimization: only call _bootstrap._lock_unlock_module() if - __spec__._initializing is true. - NOTE: because of this, initializing must be set *before* - stuffing the new module in sys.modules. + __spec__._initializing is true. + NOTE: because of this, initializing must be set *before* + stuffing the new module in sys.modules. */ spec = _PyObject_GetAttrId(mod, &PyId___spec__); if (_PyModuleSpec_IsInitializing(spec)) { @@ -1785,18 +1785,18 @@ import_find_and_load(PyThreadState *tstate, PyObject *abs_name) PyObject * PyImport_GetModule(PyObject *name) { - PyThreadState *tstate = _PyThreadState_GET(); - PyObject *mod = NULL; + PyThreadState *tstate = _PyThreadState_GET(); + PyObject *mod = NULL; - mod = import_get_module(tstate, name); - if (mod != NULL && mod != Py_None) { - if (import_ensure_initialized(tstate, mod, name) < 0) { - Py_XDECREF(mod); + mod = import_get_module(tstate, name); + if (mod != NULL && mod != Py_None) { + if (import_ensure_initialized(tstate, mod, name) < 0) { + Py_DECREF(mod); remove_importlib_frames(tstate); return NULL; - } - } - return mod; + } + } + return mod; } PyObject * From 6c1c28e4eaffaf8abb138b22bec603c8bd6c8708 Mon Sep 17 00:00:00 2001 From: Joannah Nanjekye <33177550+nanjekyejoannah@users.noreply.github.com> Date: Sat, 3 Aug 2019 12:32:58 -0300 Subject: [PATCH 06/10] Update Misc/NEWS.d/next/Library/2019-07-31-15-52-51.bpo-35943.-KswoB.rst Co-Authored-By: Serhiy Storchaka --- .../next/Library/2019-07-31-15-52-51.bpo-35943.-KswoB.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2019-07-31-15-52-51.bpo-35943.-KswoB.rst b/Misc/NEWS.d/next/Library/2019-07-31-15-52-51.bpo-35943.-KswoB.rst index 3877ba839551579..b1c55608f598ff5 100644 --- a/Misc/NEWS.d/next/Library/2019-07-31-15-52-51.bpo-35943.-KswoB.rst +++ b/Misc/NEWS.d/next/Library/2019-07-31-15-52-51.bpo-35943.-KswoB.rst @@ -1,2 +1,2 @@ The function :c:func:`PyImport_GetModule` now ensures any module it returns is fully initialized. -Patch by Joannah Nanjekye \ No newline at end of file +Patch by Joannah Nanjekye. From 13f438ef4719ed455574a05a339375b00b212fb6 Mon Sep 17 00:00:00 2001 From: Joannah Nanjekye <33177550+nanjekyejoannah@users.noreply.github.com> Date: Sat, 3 Aug 2019 12:33:09 -0300 Subject: [PATCH 07/10] Update Python/import.c Co-Authored-By: Serhiy Storchaka --- Python/import.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Python/import.c b/Python/import.c index d6439f07b2bfe0f..c016b50466f43a1 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1786,7 +1786,7 @@ PyObject * PyImport_GetModule(PyObject *name) { PyThreadState *tstate = _PyThreadState_GET(); - PyObject *mod = NULL; + PyObject *mod; mod = import_get_module(tstate, name); if (mod != NULL && mod != Py_None) { From fc83ad39cc0d0a2e9c7b2c0ec95f5d50ca633fac Mon Sep 17 00:00:00 2001 From: Joannah Nanjekye Date: Fri, 16 Aug 2019 13:43:41 +0000 Subject: [PATCH 08/10] changes to import_ensure_initialized --- Python/import.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Python/import.c b/Python/import.c index c016b50466f43a1..927b0c9512c8a58 100644 --- a/Python/import.c +++ b/Python/import.c @@ -402,16 +402,23 @@ import_ensure_initialized(PyThreadState *tstate, PyObject *mod, PyObject *name) stuffing the new module in sys.modules. */ spec = _PyObject_GetAttrId(mod, &PyId___spec__); - if (_PyModuleSpec_IsInitializing(spec)) { + if (spec == NULL) { + PyErr_Clear(); + return 0; + } + int busy = _PyModuleSpec_IsInitializing(spec); + Py_DECREF(spec); + if (busy) { + /* + Wait until module is done importing. + */ PyObject *value = _PyObject_CallMethodIdOneArg( interp->importlib, &PyId__lock_unlock_module, name); if (value == NULL) { - Py_DECREF(spec); return -1; } Py_DECREF(value); } - Py_XDECREF(spec); return 0; } From ff771e7fea799d0b8556746434f72343f0bbf3b9 Mon Sep 17 00:00:00 2001 From: Joannah Nanjekye Date: Mon, 19 Aug 2019 15:37:50 +0000 Subject: [PATCH 09/10] stop checking for spec --- Python/import.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Python/import.c b/Python/import.c index 927b0c9512c8a58..cd7a671581c4326 100644 --- a/Python/import.c +++ b/Python/import.c @@ -402,10 +402,6 @@ import_ensure_initialized(PyThreadState *tstate, PyObject *mod, PyObject *name) stuffing the new module in sys.modules. */ spec = _PyObject_GetAttrId(mod, &PyId___spec__); - if (spec == NULL) { - PyErr_Clear(); - return 0; - } int busy = _PyModuleSpec_IsInitializing(spec); Py_DECREF(spec); if (busy) { From 57dbdf5ff154a399b2bff3706ec07c82d03b8c03 Mon Sep 17 00:00:00 2001 From: Joannah Nanjekye Date: Mon, 19 Aug 2019 22:35:34 +0000 Subject: [PATCH 10/10] Remove extra vertical space --- Python/import.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Python/import.c b/Python/import.c index cd7a671581c4326..55b2ee4f2e14c5e 100644 --- a/Python/import.c +++ b/Python/import.c @@ -403,11 +403,9 @@ import_ensure_initialized(PyThreadState *tstate, PyObject *mod, PyObject *name) */ spec = _PyObject_GetAttrId(mod, &PyId___spec__); int busy = _PyModuleSpec_IsInitializing(spec); - Py_DECREF(spec); + Py_XDECREF(spec); if (busy) { - /* - Wait until module is done importing. - */ + /* Wait until module is done importing. */ PyObject *value = _PyObject_CallMethodIdOneArg( interp->importlib, &PyId__lock_unlock_module, name); if (value == NULL) {