|
1 # 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 |
|
8 import thread |
|
9 from test.test_support import verbose, TestSkipped, TestFailed |
|
10 |
|
11 critical_section = thread.allocate_lock() |
|
12 done = thread.allocate_lock() |
|
13 |
|
14 def task(): |
|
15 global N, critical_section, done |
|
16 import random |
|
17 x = random.randrange(1, 3) |
|
18 critical_section.acquire() |
|
19 N -= 1 |
|
20 # Must release critical_section before releasing done, else the main |
|
21 # thread can exit and set critical_section to None as part of global |
|
22 # teardown; then critical_section.release() raises AttributeError. |
|
23 finished = N == 0 |
|
24 critical_section.release() |
|
25 if finished: |
|
26 done.release() |
|
27 |
|
28 def test_import_hangers(): |
|
29 import sys |
|
30 if verbose: |
|
31 print "testing import hangers ...", |
|
32 |
|
33 import test.threaded_import_hangers |
|
34 try: |
|
35 if test.threaded_import_hangers.errors: |
|
36 raise TestFailed(test.threaded_import_hangers.errors) |
|
37 elif verbose: |
|
38 print "OK." |
|
39 finally: |
|
40 # In case this test is run again, make sure the helper module |
|
41 # gets loaded from scratch again. |
|
42 del sys.modules['test.threaded_import_hangers'] |
|
43 |
|
44 # Tricky: When regrtest imports this module, the thread running regrtest |
|
45 # grabs the import lock and won't let go of it until this module returns. |
|
46 # All other threads attempting an import hang for the duration. Since |
|
47 # this test spawns threads that do little *but* import, we can't do that |
|
48 # successfully until after this module finishes importing and regrtest |
|
49 # regains control. To make this work, a special case was added to |
|
50 # regrtest to invoke a module's "test_main" function (if any) after |
|
51 # importing it. |
|
52 |
|
53 def test_main(): # magic name! see above |
|
54 global N, done |
|
55 |
|
56 import imp |
|
57 if imp.lock_held(): |
|
58 # This triggers on, e.g., from test import autotest. |
|
59 raise TestSkipped("can't run when import lock is held") |
|
60 |
|
61 done.acquire() |
|
62 for N in (20, 50) * 3: |
|
63 if verbose: |
|
64 print "Trying", N, "threads ...", |
|
65 for i in range(N): |
|
66 thread.start_new_thread(task, ()) |
|
67 done.acquire() |
|
68 if verbose: |
|
69 print "OK." |
|
70 done.release() |
|
71 |
|
72 test_import_hangers() |
|
73 |
|
74 if __name__ == "__main__": |
|
75 test_main() |