[PyKDE] Broken QThread Support Under Windows

Paul Felix pef at fluent.com
Sat Dec 7 22:33:01 GMT 2002


> Qt v3.0.5 and later versions have broken threading in PyQt under Windows -
> Linux/Unix are fine. You can see the effect running the semaphore.py example.
> 
> I had a brief email exchange with somebody when this was first noticed some
> months ago, who suggested what the change in Qt might have been to cause the
> problem.
> 
> I'm now trying to get to the bottom of this - but I don't seem to have a
> record of the email exchange.
> 
> Does this ring a bell with anybody - was it you?
> 
> Thanks,
> Phil

Hi Phil,

That was me.  I was able to reproduce the problem using the C++ example.  I'm
using Windows 2000 and MSVC 6.0 SP5.

To get the C++ example to lock up, try the following:

* Change all semapahore access increment occurances from "++" to "+= 1"
* Change all semapahore access decrement occurances from "--" to "-= 1"

Obviously, you had to make that change in the PyQt example, as the "++" and
"--" operator methods are not available.

I sent a report to Trolltech, and Volker Hilsheimer tried to reproduce it,
but couldn't.  He sent me his diffs of the semaphore example code, and it
looked like he made the proper changes -- so we were stumped and I dropped it.
I'm curious to see if you can reproduce it.

Actually, now that you have resurrected this issue, I think I have found the
problem.  It's an elusive one that involves a thread race condition, so that
may explain why Volker couldn't reproduce it...

When a thread makes a call to acquire a semaphore's accesses, the call
blocks until the requested access count is available.  When another thread
releases accesses to a semaphore, the semaphore must do the following:

  1. Decrement the access count
  2. Release the waiting thread(s).

That order is quite important.  In the case of the operator+=() method, as
soon as it's thread is released, it's going to check the access count to
see if there are enough accesses available.  If there aren't enough
accesses available, it will go back into wait mode.

However, if you look at QSemaphore::operator-=() in qsemaphore_win.cpp, you
will see that the waiting threads are released BEFORE the access count is
decremented.  If you fix that order, the semaphores example (using "+=1"
and "-=1) will work.

Why did it stop working in Qt 3.0.5?  It's all a little convoluted, but the
short answer has to do with a change in QWaitCondition:wakeAll() (in
qwaitcondition_win.cpp), where a call to Windows SetEvent() was changed to
PulseEvent().

Hmmm, I just looked at Qt 3.1.0, and they changed it back to calling
SetEvent()!  So, the PyQt example may work with Qt 3.1.0!  I wonder why
they changed it back?

IMHO, the code in qsemaphore_win.cpp looks a bit questionable in places.
The code in qsemaphore_unix.cpp looks platform-independent to me -- it uses
QMutex and QWaitCondition only.  I don't know why it couldn't be used on
Windows too.  It should work, right?

Paul




More information about the PyQt mailing list