Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 48a69b7

Browse files
committed
Initial revision
1 parent 9f2a5b0 commit 48a69b7

2 files changed

Lines changed: 497 additions & 0 deletions

File tree

Demo/threads/bug.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# The following self-contained little program usually freezes with most
2+
# threads reporting
3+
#
4+
# Unhandled exception in thread:
5+
# Traceback (innermost last):
6+
# File "importbug.py", line 6
7+
# x = whrandom.randint(1,3)
8+
# AttributeError: randint
9+
#
10+
# Here's the program; it doesn't use anything from the attached module:
11+
12+
import thread
13+
14+
def task():
15+
global N
16+
import whrandom
17+
x = whrandom.randint(1,3)
18+
a.acquire()
19+
N = N - 1
20+
if N == 0: done.release()
21+
a.release()
22+
23+
a = thread.allocate_lock()
24+
done = thread.allocate_lock()
25+
N = 10
26+
27+
done.acquire()
28+
for i in range(N):
29+
thread.start_new_thread(task, ())
30+
done.acquire()
31+
print 'done'
32+
33+
34+
# Sticking an acquire/release pair around the 'import' statement makes the
35+
# problem go away.
36+
#
37+
# I believe that what happens is:
38+
#
39+
# 1) The first thread to hit the import atomically reaches, and executes
40+
# most of, get_module. In particular, it finds Lib/whrandom.pyc,
41+
# installs its name in sys.modules, and executes
42+
#
43+
# v = eval_code(co, d, d, d, (object *)NULL);
44+
#
45+
# to initialize the module.
46+
#
47+
# 2) eval_code "ticker"-slices the 1st thread out, and gives another thread
48+
# a chance. When this 2nd thread hits the same 'import', import_module
49+
# finds 'whrandom' in sys.modules, so just proceeds.
50+
#
51+
# 3) But the 1st thread is still "in the middle" of executing whrandom.pyc.
52+
# So the 2nd thread has a good chance of trying to look up 'randint'
53+
# before the 1st thread has placed it in whrandom's dict.
54+
#
55+
# 4) The more threads there are, the more likely that at least one of them
56+
# will do this before the 1st thread finishes the import work.
57+
#
58+
# If that's right, a perhaps not-too-bad workaround would be to introduce a
59+
# static "you can't interrupt this thread" flag in ceval.c, check it before
60+
# giving up interpreter_lock, and have IMPORT_NAME set it & restore (plain
61+
# clearing would not work) it around its call to import_module. To its
62+
# credit, there's something wonderfully perverse about fixing a race via an
63+
# unprotected static <grin>.
64+
#
65+
# as-with-most-other-things-(pseudo-)parallel-programming's-more-fun-
66+
# in-python-too!-ly y'rs - tim
67+
#
68+
# Tim Peters [email protected]
69+
# not speaking for Kendall Square Research Corp

0 commit comments

Comments
 (0)