blob: 6cedb9615b45f20a830a19310919e2983fad8467 [file] [log] [blame]
Tim Petersaa222232001-05-22 09:34:27 +00001# This is a variant of the very old (early 90's) file
2# Demo/threads/bug.py. It simply provokes a number of threads into
3# trying to import the same module "at the same time".
4# There are no pleasant failure modes -- most likely is that Python
5# complains several times about module random having no attribute
6# randrange, and then Python hangs.
7
Antoine Pitrou1f9dea02010-07-14 11:52:38 +00008import imp
9import sys
Georg Brandl89fad142010-03-14 10:23:39 +000010import unittest
Antoine Pitrou1f9dea02010-07-14 11:52:38 +000011from test.support import verbose, TestFailed, import_module, run_unittest
Victor Stinner45df8202010-04-28 22:31:17 +000012thread = import_module('_thread')
Tim Petersaa222232001-05-22 09:34:27 +000013
Antoine Pitrou1f9dea02010-07-14 11:52:38 +000014def task(N, done, done_tasks, errors):
15 try:
16 import random
17 # This will fail if random is not completely initialized
18 x = random.randrange(1, 3)
19 except Exception as e:
20 errors.append(e.with_traceback(None))
21 finally:
22 done_tasks.append(thread.get_ident())
23 finished = len(done_tasks) == N
24 if finished:
25 done.release()
Tim Petersaa222232001-05-22 09:34:27 +000026
Antoine Pitrou1f9dea02010-07-14 11:52:38 +000027
28class ThreadedImportTests(unittest.TestCase):
29
Antoine Pitrou448acd02010-07-16 19:10:38 +000030 def setUp(self):
31 self.old_random = sys.modules.pop('random', None)
32
33 def tearDown(self):
34 # If the `random` module was already initialized, we restore the
35 # old module at the end so that pickling tests don't fail.
36 # See http://bugs.python.org/issue3657#msg110461
37 if self.old_random is not None:
38 sys.modules['random'] = self.old_random
39
Antoine Pitrou1f9dea02010-07-14 11:52:38 +000040 def test_parallel_module_init(self):
41 if imp.lock_held():
42 # This triggers on, e.g., from test import autotest.
43 raise unittest.SkipTest("can't run when import lock is held")
44
45 done = thread.allocate_lock()
46 done.acquire()
47 for N in (20, 50) * 3:
48 if verbose:
49 print("Trying", N, "threads ...", end=' ')
50 # Make sure that random gets reimported freshly
51 try:
52 del sys.modules['random']
53 except KeyError:
54 pass
55 errors = []
56 done_tasks = []
57 for i in range(N):
58 thread.start_new_thread(task, (N, done, done_tasks, errors,))
59 done.acquire()
60 self.assertFalse(errors)
61 if verbose:
62 print("OK.")
Tim Peters20882dd2002-02-16 07:26:27 +000063 done.release()
Tim Petersaa222232001-05-22 09:34:27 +000064
Antoine Pitrou1f9dea02010-07-14 11:52:38 +000065 def test_import_hangers(self):
Thomas Wouters477c8d52006-05-27 19:21:47 +000066 # In case this test is run again, make sure the helper module
67 # gets loaded from scratch again.
Antoine Pitrou1f9dea02010-07-14 11:52:38 +000068 try:
69 del sys.modules['test.threaded_import_hangers']
70 except KeyError:
71 pass
72 import test.threaded_import_hangers
73 self.assertFalse(test.threaded_import_hangers.errors)
Thomas Wouters477c8d52006-05-27 19:21:47 +000074
Tim Petersaa222232001-05-22 09:34:27 +000075
Antoine Pitrou1f9dea02010-07-14 11:52:38 +000076def test_main():
77 run_unittest(ThreadedImportTests)
Tim Peters69232342001-08-30 05:16:13 +000078
Thomas Wouters477c8d52006-05-27 19:21:47 +000079
Tim Petersd9742212001-05-22 18:28:25 +000080if __name__ == "__main__":
81 test_main()