Using time.sleep() in 2 threads causes lockup when hyper-threading is enabled
Tim Peters
tim.peters at gmail.com
Wed May 3 16:55:35 EDT 2006
[OlafMeding at gmail.com]
> Below are 2 files that isolate the problem. Note, both programs hang
> (stop responding)
What does "stop responding" mean?
> with hyper-threading turned on (a BIOS setting), but
> work as expected with hyper-threading turned off.
>
> Note, the Windows task manager shows 2 CPUs on the Performance tab with
> hyper-threading is turned on.
>
> Both Python 2.3.5 and 2.4.3 (downloaded from python.org) have this
> problem.
> The operating system is MS Windows XP Professional.
>
> winmsd.exe shows:
> 2CPUs: x86 Family 15 Model 4 Stepping 1 GenuineIntel ~3000 MHz
> Version: 5.1.2600 Service Pack 2 Build 2600
>
> Could someone with a hyper-threading (or dual/multicore) CPU please
> confirm this bug?
I don't see anything unexpected (to me) on a WinXP Pro SP2 box with HT
enabled, using 2.4.3, but I'm not sure what "not responding" means to
you.
> # testsleep.py
> import threading
> import time
>
> class Task(threading.Thread):
> def __init__(self, n, t):
> threading.Thread.__init__(self)
> self.n = n
> self.t = t
> def run(self):
> print 'thread %d started' % self.n
> print 'sleep time:', self.t
> print time.clock()
> print time.clock()
> print time.clock()
> print
> count = 0
> printCount = int(10 / self.t)
> while True:
> start = time.clock()
> time.sleep(self.t)
> stop = time.clock()
> if stop - start > 1.0:
> print 'thread', self.n, stop - start
You don't _expect_ this print to execute, do you? It should trigger
very rarely (if ever).
> count += 1
> if count > printCount:
> count = 0
> print self.n,
>
> def test():
> thread1 = Task(1, 0.01)
> thread2 = Task(2, 0.003)
> thread1.start()
> thread2.start()
>
> test()
This is what happened when I ran it, until I got tired of watching it
and killed the job:
C:\Python24>python test1.py
thread 1 started
sleep time: 0.01
7.8499538238e-007
4.42770924877e-005
8.62618455186e-005
thread 2 started
sleep time: 0.003
0.000479349533238
0.000521904282916
0.000563649037359
1 2 1 2 1 2 1 2 1 1 2 1 2 1 2 1 2 1 2 1 1 2 1 2 1
2 1 2 1 2 1 1 2 1 2 1 2 1 2 1 1 2 1 2 1 2 1 2 1 2
1 1 2 1 2 1 2 1 2 1 2 1 1 2 1 2 1 2 1 2 1
> # testsleep2.py
> import thread
> import time
> import sys
>
> def run(n, t):
> print 'thread %d started' % n
> print 'sleep time:', t
> print time.clock()
> print time.clock()
> print time.clock()
> print
> count = 0
> printCount = int(10 / t)
> while True:
> start = time.clock()
> time.sleep(t)
> stop = time.clock()
> if stop - start > 1.0:
> print 'thread', n, stop - start
See above.
> count += 1
> if count > printCount:
> count = 0
> print n,
>
> def test():
> thread.start_new_thread(run, (1, 0.01))
> thread.start_new_thread(run, (2, 0.003))
>
> # Wait until the user presses the enter key.
> sys.stdin.read(1)
Do you want someone running this test to hit the ENTER key, or not?
>
> test()
Works much the same for me, except I got bored quicker ;-):
C:\Python24>python test2..py
thread 1 started
sleep time: 0.01
1.14999323533e-006
8.01271757225e-005
thread 2 started
sleep time: 0.003
0.000395865318439
0.000474259857295
0.000559831706872
0.00071061346698
1 2 1 2 1 2 1 2 1 1 2 1 2 1 2 1 2 1 2 1
At that point I hit the ENTER key, and saw:
Unhandled exception in thread started by
Error in sys.excepthook:
Original exception was:
Unhandled exception in thread started by
Error in sys.excepthook:
Original exception was:
That's unfortunate, but not unexpected either. The interpreter
doesn't wait for a `thread` module thread to finish before tearing
itself down, so the threads keep running after Python has torn so much
of itself down that weird execptions occur -- and Python is _so_ torn
down by that point it can't even display a useful error message. The
interpreter does (by default) wait for `threading` module threads to
exit before tearing itself down, so those kinds of useless exit
messages weren't expected in the first test.
More information about the Python-list
mailing list