I was reminded of this one while working on the Spyce/Durus demo to make it a better example of using Durus in a real application.
What is wrong with the following code?
A.py:
import time, threading finished = False def foo(): import sys sys.stderr.write('testing') global finished finished = True threading.Thread(target=foo).start() while not finished: time.sleep(1)
B.py:
import A print 'finished'
Update: fixed A.py so there was only one problem.
Comments
If that's it, you've done a good job of hiding a really obvious problem by introducing threading into the mix. It took me a while to see it because I was expecting something to be wrong with the threading logic.
Which is interesting. I've always sworn threading introduces a whole slew of new problems and should be avoided if at all possible but I never considered that it might also have the effect of hiding well-known problems. :)
Nice.
Did I mention how much I dislike threading? ;)
What actually *is* so bad about threading? And what do you use as a cross platform alternative?
So here, the deadlock is that the main thread has the import lock ("import A"), but since it's waiting for _t to set finished, it will never release the lock and _t is forever stuck at "import sys."
I have a system that automatically starts threads to do background computations. The idea is similar to futures (http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/84317).
The trouble is that the various functions that are creating these futures might very well be used naïvely in a module of shared utility routines. It’s unreasonable for me to say to the users of the system “Oh, and by the way, you can’t do this.”
Anyway, is there any way to work around this? My own code does not import within functions, but a number of standard library calls *do*. (For example, os.execvp.)