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