annotate Lib/test/test_threaded_import.py @ 78069:a8aa77458e12 3.2

Add c_size_t and c_ssize_t to the ctypes summary table.
author Antoine Pitrou <solipsis@pitrou.net>
date Thu, 12 Jul 2012 20:31:50 +0200
parents 3c9232a684ae
children 5548197d1f22
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
17897
cc984ed26586 New test adapted from the ancient Demo/threads/bug.py.
Tim Peters <tim.peters@gmail.com>
parents:
diff changeset
1 # This is a variant of the very old (early 90's) file
cc984ed26586 New test adapted from the ancient Demo/threads/bug.py.
Tim Peters <tim.peters@gmail.com>
parents:
diff changeset
2 # Demo/threads/bug.py. It simply provokes a number of threads into
cc984ed26586 New test adapted from the ancient Demo/threads/bug.py.
Tim Peters <tim.peters@gmail.com>
parents:
diff changeset
3 # trying to import the same module "at the same time".
cc984ed26586 New test adapted from the ancient Demo/threads/bug.py.
Tim Peters <tim.peters@gmail.com>
parents:
diff changeset
4 # There are no pleasant failure modes -- most likely is that Python
cc984ed26586 New test adapted from the ancient Demo/threads/bug.py.
Tim Peters <tim.peters@gmail.com>
parents:
diff changeset
5 # complains several times about module random having no attribute
cc984ed26586 New test adapted from the ancient Demo/threads/bug.py.
Tim Peters <tim.peters@gmail.com>
parents:
diff changeset
6 # randrange, and then Python hangs.
cc984ed26586 New test adapted from the ancient Demo/threads/bug.py.
Tim Peters <tim.peters@gmail.com>
parents:
diff changeset
7
64238
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
8 import os
63024
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
9 import imp
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
10 import sys
64238
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
11 import time
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
12 import shutil
63024
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
13 import unittest
64238
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
14 from test.support import verbose, import_module, run_unittest, TESTFN
63024
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
15 thread = import_module('_thread')
64238
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
16 threading = import_module('threading')
17897
cc984ed26586 New test adapted from the ancient Demo/threads/bug.py.
Tim Peters <tim.peters@gmail.com>
parents:
diff changeset
17
63024
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
18 def task(N, done, done_tasks, errors):
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
19 try:
64238
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
20 # We don't use modulefinder but still import it in order to stress
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
21 # importing of different modules from several threads.
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
22 if len(done_tasks) % 2:
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
23 import modulefinder
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
24 import random
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
25 else:
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
26 import random
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
27 import modulefinder
63024
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
28 # This will fail if random is not completely initialized
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
29 x = random.randrange(1, 3)
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
30 except Exception as e:
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
31 errors.append(e.with_traceback(None))
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
32 finally:
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
33 done_tasks.append(thread.get_ident())
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
34 finished = len(done_tasks) == N
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
35 if finished:
65280
1e72abf073c5 Merged revisions 85444 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 64238
diff changeset
36 done.set()
63024
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
37
64238
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
38 # Create a circular import structure: A -> C -> B -> D -> A
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
39 # NOTE: `time` is already loaded and therefore doesn't threaten to deadlock.
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
40
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
41 circular_imports_modules = {
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
42 'A': """if 1:
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
43 import time
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
44 time.sleep(%(delay)s)
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
45 x = 'a'
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
46 import C
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
47 """,
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
48 'B': """if 1:
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
49 import time
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
50 time.sleep(%(delay)s)
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
51 x = 'b'
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
52 import D
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
53 """,
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
54 'C': """import B""",
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
55 'D': """import A""",
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
56 }
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
57
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
58 class Finder:
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
59 """A dummy finder to detect concurrent access to its find_module()
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
60 method."""
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
61
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
62 def __init__(self):
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
63 self.numcalls = 0
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
64 self.x = 0
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
65 self.lock = thread.allocate_lock()
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
66
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
67 def find_module(self, name, path=None):
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
68 # Simulate some thread-unsafe behaviour. If calls to find_module()
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
69 # are properly serialized, `x` will end up the same as `numcalls`.
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
70 # Otherwise not.
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
71 with self.lock:
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
72 self.numcalls += 1
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
73 x = self.x
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
74 time.sleep(0.1)
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
75 self.x = x + 1
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
76
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
77 class FlushingFinder:
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
78 """A dummy finder which flushes sys.path_importer_cache when it gets
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
79 called."""
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
80
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
81 def find_module(self, name, path=None):
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
82 sys.path_importer_cache.clear()
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
83
63024
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
84
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
85 class ThreadedImportTests(unittest.TestCase):
17897
cc984ed26586 New test adapted from the ancient Demo/threads/bug.py.
Tim Peters <tim.peters@gmail.com>
parents:
diff changeset
86
63045
7cbf8c4e2727 Merged revisions 82919 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63024
diff changeset
87 def setUp(self):
7cbf8c4e2727 Merged revisions 82919 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63024
diff changeset
88 self.old_random = sys.modules.pop('random', None)
7cbf8c4e2727 Merged revisions 82919 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63024
diff changeset
89
7cbf8c4e2727 Merged revisions 82919 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63024
diff changeset
90 def tearDown(self):
7cbf8c4e2727 Merged revisions 82919 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63024
diff changeset
91 # If the `random` module was already initialized, we restore the
7cbf8c4e2727 Merged revisions 82919 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63024
diff changeset
92 # old module at the end so that pickling tests don't fail.
7cbf8c4e2727 Merged revisions 82919 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63024
diff changeset
93 # See http://bugs.python.org/issue3657#msg110461
7cbf8c4e2727 Merged revisions 82919 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63024
diff changeset
94 if self.old_random is not None:
7cbf8c4e2727 Merged revisions 82919 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63024
diff changeset
95 sys.modules['random'] = self.old_random
7cbf8c4e2727 Merged revisions 82919 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63024
diff changeset
96
64238
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
97 def check_parallel_module_init(self):
63024
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
98 if imp.lock_held():
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
99 # This triggers on, e.g., from test import autotest.
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
100 raise unittest.SkipTest("can't run when import lock is held")
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
101
65280
1e72abf073c5 Merged revisions 85444 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 64238
diff changeset
102 done = threading.Event()
63024
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
103 for N in (20, 50) * 3:
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
104 if verbose:
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
105 print("Trying", N, "threads ...", end=' ')
64238
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
106 # Make sure that random and modulefinder get reimported freshly
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
107 for modname in ['random', 'modulefinder']:
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
108 try:
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
109 del sys.modules[modname]
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
110 except KeyError:
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
111 pass
63024
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
112 errors = []
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
113 done_tasks = []
65280
1e72abf073c5 Merged revisions 85444 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 64238
diff changeset
114 done.clear()
63024
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
115 for i in range(N):
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
116 thread.start_new_thread(task, (N, done, done_tasks, errors,))
65280
1e72abf073c5 Merged revisions 85444 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 64238
diff changeset
117 done.wait(60)
63024
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
118 self.assertFalse(errors)
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
119 if verbose:
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
120 print("OK.")
17897
cc984ed26586 New test adapted from the ancient Demo/threads/bug.py.
Tim Peters <tim.peters@gmail.com>
parents:
diff changeset
121
64238
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
122 def test_parallel_module_init(self):
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
123 self.check_parallel_module_init()
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
124
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
125 def test_parallel_meta_path(self):
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
126 finder = Finder()
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
127 sys.meta_path.append(finder)
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
128 try:
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
129 self.check_parallel_module_init()
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
130 self.assertGreater(finder.numcalls, 0)
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
131 self.assertEqual(finder.x, finder.numcalls)
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
132 finally:
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
133 sys.meta_path.remove(finder)
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
134
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
135 def test_parallel_path_hooks(self):
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
136 # Here the Finder instance is only used to check concurrent calls
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
137 # to path_hook().
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
138 finder = Finder()
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
139 # In order for our path hook to be called at each import, we need
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
140 # to flush the path_importer_cache, which we do by registering a
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
141 # dedicated meta_path entry.
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
142 flushing_finder = FlushingFinder()
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
143 def path_hook(path):
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
144 finder.find_module('')
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
145 raise ImportError
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
146 sys.path_hooks.append(path_hook)
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
147 sys.meta_path.append(flushing_finder)
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
148 try:
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
149 # Flush the cache a first time
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
150 flushing_finder.find_module('')
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
151 numtests = self.check_parallel_module_init()
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
152 self.assertGreater(finder.numcalls, 0)
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
153 self.assertEqual(finder.x, finder.numcalls)
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
154 finally:
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
155 sys.meta_path.remove(flushing_finder)
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
156 sys.path_hooks.remove(path_hook)
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
157
63024
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
158 def test_import_hangers(self):
38453
29ae5e0fc348 Much-needed merge (using svnmerge.py this time) of trunk changes into p3yk.
Thomas Wouters <thomas@python.org>
parents: 32918
diff changeset
159 # In case this test is run again, make sure the helper module
29ae5e0fc348 Much-needed merge (using svnmerge.py this time) of trunk changes into p3yk.
Thomas Wouters <thomas@python.org>
parents: 32918
diff changeset
160 # gets loaded from scratch again.
63024
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
161 try:
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
162 del sys.modules['test.threaded_import_hangers']
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
163 except KeyError:
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
164 pass
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
165 import test.threaded_import_hangers
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
166 self.assertFalse(test.threaded_import_hangers.errors)
19596
1be18ef869a4 Add a new function imp.lock_held(), and use it to skip test_threaded_import
Tim Peters <tim.peters@gmail.com>
parents: 19564
diff changeset
167
64238
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
168 def test_circular_imports(self):
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
169 # The goal of this test is to exercise implementations of the import
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
170 # lock which use a per-module lock, rather than a global lock.
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
171 # In these implementations, there is a possible deadlock with
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
172 # circular imports, for example:
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
173 # - thread 1 imports A (grabbing the lock for A) which imports B
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
174 # - thread 2 imports B (grabbing the lock for B) which imports A
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
175 # Such implementations should be able to detect such situations and
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
176 # resolve them one way or the other, without freezing.
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
177 # NOTE: our test constructs a slightly less trivial import cycle,
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
178 # in order to better stress the deadlock avoidance mechanism.
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
179 delay = 0.5
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
180 os.mkdir(TESTFN)
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
181 self.addCleanup(shutil.rmtree, TESTFN)
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
182 sys.path.insert(0, TESTFN)
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
183 self.addCleanup(sys.path.remove, TESTFN)
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
184 for name, contents in circular_imports_modules.items():
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
185 contents = contents % {'delay': delay}
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
186 with open(os.path.join(TESTFN, name + ".py"), "wb") as f:
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
187 f.write(contents.encode('utf-8'))
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
188 self.addCleanup(sys.modules.pop, name, None)
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
189
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
190 results = []
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
191 def import_ab():
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
192 import A
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
193 results.append(getattr(A, 'x', None))
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
194 def import_ba():
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
195 import B
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
196 results.append(getattr(B, 'x', None))
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
197 t1 = threading.Thread(target=import_ab)
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
198 t2 = threading.Thread(target=import_ba)
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
199 t1.start()
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
200 t2.start()
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
201 t1.join()
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
202 t2.join()
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
203 self.assertEqual(set(results), {'a', 'b'})
716d3d102c0a Merged revisions 84258,84268 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 63045
diff changeset
204
19596
1be18ef869a4 Add a new function imp.lock_held(), and use it to skip test_threaded_import
Tim Peters <tim.peters@gmail.com>
parents: 19564
diff changeset
205
63024
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
206 def test_main():
3805ffe8ff38 Merged revisions 82885 via svnmerge from
Antoine Pitrou <solipsis@pitrou.net>
parents: 52389
diff changeset
207 run_unittest(ThreadedImportTests)
17897
cc984ed26586 New test adapted from the ancient Demo/threads/bug.py.
Tim Peters <tim.peters@gmail.com>
parents:
diff changeset
208
17913
46909f22170c Implementing an idea from Guido on the checkins list:
Tim Peters <tim.peters@gmail.com>
parents: 17897
diff changeset
209 if __name__ == "__main__":
46909f22170c Implementing an idea from Guido on the checkins list:
Tim Peters <tim.peters@gmail.com>
parents: 17897
diff changeset
210 test_main()