While playing Starcraft with the ddraw patch (this effectively uncovers
race condition problems, since then the game freezes and I get angry, but
since I can't play on anyway, I attach some gdbs)

I think I've uncovered one in QUEUE_WaitBits. In windows/queue.c, there's
this:

int QUEUE_WaitBits( WORD bits, DWORD timeout )
{
[1] MESSAGEQUEUE *queue
...
    for (;;)
    {
[2]     if (queue->changeBits & bits)
        {
            /* One of the bits is set; we can return */
            queue->wakeMask = 0;                       
            QUEUE_Unlock( queue );
            return 1;
        }
        if (queue->wakeBits & QS_SENDMESSAGE)
        {
            /* Process the sent message immediately */

            queue->wakeMask = 0;
            QUEUE_ReceiveMessage( queue );
            continue;                           /* nested sm crux */
        }

        queue->wakeMask = bits | QS_SENDMESSAGE;
[3]     if(queue->changeBits & bits)
        {
            continue;
        }
...

OK, this code may look all fine and dandy, even for sendmessages. But what
happens when an optimizing C compiler like gcc gets run on it? Well, it
figures that the changeBits are tested at [2], so when it gets to [3], it
sees no change, and optimizes [3] out... so, instant race condition.
Obviously, we need to add a "volatile" here somewhere (no, this is not a
gcc bug), but perhaps someone that doesn't like unnecessary compiler
warnings can think of a better place to put this "volatile" than [1] ?
(Or Alexandre can fix it himself?)


Reply via email to