This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author kristjan.jonsson
Recipients kristjan.jonsson, loewis, paul.moore, pitrou, python-dev, sbt, vstinner
Date 2012-06-19.09:44:47
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1340099090.49.0.339469907711.issue15038@psf.upfronthosting.co.za>
In-reply-to
Content
You are right, Richard.  Thanks for pointing this out.  This is not a new problem, however, because this code has been in the New GIL since it was launched.

The purpose of the "n_waiting" member is to make "signal" a no-op when no one is there waiting.  Otherwise, we could increase the semaphore's internal count without bound, since the condition variable protocol allows "signal" to be called as often as one desires.
It is important that it doesn't fall out of sync with the actual semaphore count.  Normally what will happen when the race occurs is this:
n_waiting will be double decremented, and semaphore internal count will be increased by one (the wait timed out, yet we called signal).  Thus, for example, we could end up with the idle state of semaphore_count == 1 and n_waiting == -1.  (the invariant is semaphore_count + n_waiting - waiting_threads == 0)

When the next waiter comes along, with semaphore count==1, it will just pass though, having incremented n_waiting to 0.

The problem you describe is that if if 'signal' is ever hit with n_waiting<0, it will continue to tip this balance.  What this will do is just cause the semaphore count to start growing.  And thus, we have defeated the purpose of n_waiting.  This oversight is my fault.  However rest assured that it is rare, having been in the new GIL implementation since its launch :)

There are two fixes:
1) As you describe, make a positive test in the "signal".
2) Make the waiter the only one who updates n_waiting, whenever it wakes up.  The side effect of this is a possible slight increase of spurious wakeups in some usage scenarios.  But it is simpler.

I'll implement number 1), and improve the documentation to that effect.
History
Date User Action Args
2012-06-19 09:44:50kristjan.jonssonsetrecipients: + kristjan.jonsson, loewis, paul.moore, pitrou, vstinner, python-dev, sbt
2012-06-19 09:44:50kristjan.jonssonsetmessageid: <1340099090.49.0.339469907711.issue15038@psf.upfronthosting.co.za>
2012-06-19 09:44:49kristjan.jonssonlinkissue15038 messages
2012-06-19 09:44:47kristjan.jonssoncreate