Skip to content

Commit

Permalink
[3.9] bpo-43517: Fix false positive in detection of circular imports (G…
Browse files Browse the repository at this point in the history
…H-24895) (GH-24948)

(cherry picked from commit 2fd16ef)

Co-authored-by: Antoine Pitrou <antoine@python.org>

Automerge-Triggered-By: GH:pitrou
  • Loading branch information
pitrou committed Mar 20, 2021
1 parent e8e3419 commit ac17ed6
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 2 deletions.
38 changes: 38 additions & 0 deletions Lib/test/test_importlib/partial/cfimport.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import os
import sys
import threading
import traceback


NLOOPS = 50
NTHREADS = 30


def t1():
try:
from concurrent.futures import ThreadPoolExecutor
except Exception:
traceback.print_exc()
os._exit(1)

def t2():
try:
from concurrent.futures.thread import ThreadPoolExecutor
except Exception:
traceback.print_exc()
os._exit(1)

def main():
for j in range(NLOOPS):
threads = []
for i in range(NTHREADS):
threads.append(threading.Thread(target=t2 if i % 1 else t1))
for thread in threads:
thread.start()
for thread in threads:
thread.join()
sys.modules.pop('concurrent.futures', None)
sys.modules.pop('concurrent.futures.thread', None)

if __name__ == "__main__":
main()
27 changes: 27 additions & 0 deletions Lib/test/test_importlib/partial/pool_in_threads.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import multiprocessing
import os
import threading
import traceback


def t():
try:
with multiprocessing.Pool(1):
pass
except Exception:
traceback.print_exc()
os._exit(1)


def main():
threads = []
for i in range(20):
threads.append(threading.Thread(target=t))
for thread in threads:
thread.start()
for thread in threads:
thread.join()


if __name__ == "__main__":
main()
14 changes: 13 additions & 1 deletion Lib/test/test_importlib/test_threaded_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from unittest import mock
from test.support import (
verbose, run_unittest, TESTFN, reap_threads,
forget, unlink, rmtree, start_threads)
forget, unlink, rmtree, start_threads, script_helper)

def task(N, done, done_tasks, errors):
try:
Expand Down Expand Up @@ -244,6 +244,18 @@ def target():
__import__(TESTFN)
del sys.modules[TESTFN]

def test_concurrent_futures_circular_import(self):
# Regression test for bpo-43515
fn = os.path.join(os.path.dirname(__file__),
'partial', 'cfimport.py')
script_helper.assert_python_ok(fn)

def test_multiprocessing_pool_circular_import(self):
# Regression test for bpo-41567
fn = os.path.join(os.path.dirname(__file__),
'partial', 'pool_in_threads.py')
script_helper.assert_python_ok(fn)


@reap_threads
def test_main():
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix misdetection of circular imports when using ``from pkg.mod import
attr``, which caused false positives in non-trivial multi-threaded code.
2 changes: 1 addition & 1 deletion Python/import.c
Original file line number Diff line number Diff line change
Expand Up @@ -1863,7 +1863,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
}

if (mod != NULL && mod != Py_None) {
if (import_ensure_initialized(tstate, mod, name) < 0) {
if (import_ensure_initialized(tstate, mod, abs_name) < 0) {
goto error;
}
}
Expand Down

0 comments on commit ac17ed6

Please sign in to comment.