[PyKDE] Broken QThread Support Under Windows

Phil Thompson phil at river-bank.demon.co.uk
Sun Dec 8 19:03:01 GMT 2002


Paul,

Thanks for this - it was very helpful.

I had tried Qt 3.1.0 but it didn't seem to have improved things.

I then changed the implementation of QSemaphore.__iadd__() and __isub__ so 
that they used ++ (and --) instead of += (and -=) when the value was one. The 
semaphore.py script now works with Qt 3.0.5. I haven't yet tested against Qt 
3.1.0, but I feel confident it will work.

Phil

On Saturday 07 December 2002 9:31 pm, Paul Felix wrote:
> > 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