Remove bug.py. This is something I sent to Guido via email in or before
'94, demonstrating a thread bug that was later repaired via Python growing an internal import lock. It's of no current interest, and the now-std test_threaded_import.py is pretty much the same test.
This commit is contained in:
parent
fdba55fe8e
commit
4843eb400b
|
@ -3,7 +3,6 @@ This directory contains some demonstrations of the thread module.
|
|||
These are mostly "proof of concept" type applications:
|
||||
|
||||
Generator.py Generator class implemented with threads.
|
||||
bug.py Demonstrate a bug with importing modules in threads.
|
||||
find.py Parallelized "find(1)" (looks for directories).
|
||||
sync.py Condition variables primitives by Tim Peters.
|
||||
telnet.py Version of ../sockets/telnet.py using threads.
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
# The following self-contained little program usually freezes with most
|
||||
# threads reporting
|
||||
#
|
||||
# Unhandled exception in thread:
|
||||
# Traceback (innermost last):
|
||||
# File "importbug.py", line 6
|
||||
# x = whrandom.randint(1,3)
|
||||
# AttributeError: randint
|
||||
#
|
||||
# Here's the program; it doesn't use anything from the attached module:
|
||||
|
||||
import thread
|
||||
|
||||
def task():
|
||||
global N
|
||||
import whrandom
|
||||
x = whrandom.randint(1,3)
|
||||
a.acquire()
|
||||
N = N - 1
|
||||
if N == 0: done.release()
|
||||
a.release()
|
||||
|
||||
a = thread.allocate_lock()
|
||||
done = thread.allocate_lock()
|
||||
N = 10
|
||||
|
||||
done.acquire()
|
||||
for i in range(N):
|
||||
thread.start_new_thread(task, ())
|
||||
done.acquire()
|
||||
print 'done'
|
||||
|
||||
|
||||
# Sticking an acquire/release pair around the 'import' statement makes the
|
||||
# problem go away.
|
||||
#
|
||||
# I believe that what happens is:
|
||||
#
|
||||
# 1) The first thread to hit the import atomically reaches, and executes
|
||||
# most of, get_module. In particular, it finds Lib/whrandom.pyc,
|
||||
# installs its name in sys.modules, and executes
|
||||
#
|
||||
# v = eval_code(co, d, d, d, (object *)NULL);
|
||||
#
|
||||
# to initialize the module.
|
||||
#
|
||||
# 2) eval_code "ticker"-slices the 1st thread out, and gives another thread
|
||||
# a chance. When this 2nd thread hits the same 'import', import_module
|
||||
# finds 'whrandom' in sys.modules, so just proceeds.
|
||||
#
|
||||
# 3) But the 1st thread is still "in the middle" of executing whrandom.pyc.
|
||||
# So the 2nd thread has a good chance of trying to look up 'randint'
|
||||
# before the 1st thread has placed it in whrandom's dict.
|
||||
#
|
||||
# 4) The more threads there are, the more likely that at least one of them
|
||||
# will do this before the 1st thread finishes the import work.
|
||||
#
|
||||
# If that's right, a perhaps not-too-bad workaround would be to introduce a
|
||||
# static "you can't interrupt this thread" flag in ceval.c, check it before
|
||||
# giving up interpreter_lock, and have IMPORT_NAME set it & restore (plain
|
||||
# clearing would not work) it around its call to import_module. To its
|
||||
# credit, there's something wonderfully perverse about fixing a race via an
|
||||
# unprotected static <grin>.
|
||||
#
|
||||
# as-with-most-other-things-(pseudo-)parallel-programming's-more-fun-
|
||||
# in-python-too!-ly y'rs - tim
|
||||
#
|
||||
# Tim Peters tim@ksr.com
|
||||
# not speaking for Kendall Square Research Corp
|
Loading…
Reference in New Issue