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