mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
bpo-43517: Fix false positive in detection of circular imports (#24895)
This commit is contained in:
parent
7cb033c423
commit
2fd16ef406
5 changed files with 81 additions and 2 deletions
38
Lib/test/test_importlib/partial/cfimport.py
Normal file
38
Lib/test/test_importlib/partial/cfimport.py
Normal file
|
@ -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
Lib/test/test_importlib/partial/pool_in_threads.py
Normal file
27
Lib/test/test_importlib/partial/pool_in_threads.py
Normal file
|
@ -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()
|
|
@ -17,7 +17,7 @@ from unittest import mock
|
||||||
from test.support import (verbose, run_unittest)
|
from test.support import (verbose, run_unittest)
|
||||||
from test.support.import_helper import forget
|
from test.support.import_helper import forget
|
||||||
from test.support.os_helper import (TESTFN, unlink, rmtree)
|
from test.support.os_helper import (TESTFN, unlink, rmtree)
|
||||||
from test.support import threading_helper
|
from test.support import script_helper, threading_helper
|
||||||
|
|
||||||
def task(N, done, done_tasks, errors):
|
def task(N, done, done_tasks, errors):
|
||||||
try:
|
try:
|
||||||
|
@ -245,6 +245,18 @@ class ThreadedImportTests(unittest.TestCase):
|
||||||
__import__(TESTFN)
|
__import__(TESTFN)
|
||||||
del sys.modules[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)
|
||||||
|
|
||||||
|
|
||||||
@threading_helper.reap_threads
|
@threading_helper.reap_threads
|
||||||
def test_main():
|
def test_main():
|
||||||
|
|
|
@ -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.
|
|
@ -1593,7 +1593,7 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mod != NULL && mod != Py_None) {
|
if (mod != NULL && mod != Py_None) {
|
||||||
if (import_ensure_initialized(tstate->interp, mod, name) < 0) {
|
if (import_ensure_initialized(tstate->interp, mod, abs_name) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue