开发者

Problem with perror() calls affecting semaphore locking/unlocking

I'm trying to do some basic parallel processing to do an odd-even sort on integers using POSIX shared memory segments and unnamed semaphores. I have pretty much everything working at this point, except for one final thing: if I do not perror() directly after semaphore locks/unlocks the code acts differently (and subsequently sorts incorrectly). If I leave the perror() calls directly after semaphore locks and unlocks in, the code sorts the array of integers perfectly.

int semaphoreCheck = sem_init(&(sharedData->swapSem), 1, 1);

if (semaphoreCheck == -1)
{
    p开发者_开发百科error( "failed to initialize semaphore" );
    exit(EXIT_FAILURE);
}

pid_t fork1;
fork1 = fork();
if (fork1 == 0)
{
    // original.child
    pid_t fork2;
    fork2 = fork();
    if (fork2 == 0)
    {
        // child.child
        // do a portion of the sort here
        while(sharedData->evenSwap || sharedData->oddSwap)
        {
            // obtain lock on the shared vector
            // int commandCheck = shmctl(sharedID, SHM_LOCK, NULL);
            int commandCheck = sem_wait(&(sharedData->swapSem));
            perror("semaphore lock");
            // if lock was obtained
            if (commandCheck == 0)
            {
                sharedData->evenSwap = false;
                for( int index = 1; index < arraySize - 1; index +=2)
                {
                    if( sharedData->vecData[index] > sharedData->vecData[index + 1] )   
                    {
                        int temp;
                        temp = sharedData->vecData[index];
                        sharedData->vecData[index] = sharedData->vecData[index+1];
                        sharedData->vecData[index+1] = temp;
                        sharedData->evenSwap = true;
                    }       
                }
                // release lock on the shared vector
                commandCheck = sem_post(&(sharedData->swapSem));
                perror("semaphore unlock");
                if (commandCheck == -1)
                {
                    perror("failed to unlock shared semaphore");
                }
            }
            else perror("failed to lock shared semaphore");
        }
        _exit(0);
    }
    else if (fork2 > 0)
    {
        // child.parent
        // do a portion of the sort here
        while(sharedData->evenSwap || sharedData->oddSwap)
        {
            // obtain lock on the shared vector
            int commandCheck = sem_wait(&(sharedData->swapSem));
            perror("semaphore lock");
            // if lock was obtained
            if (commandCheck == 0)
            {
                sharedData->oddSwap = false;
                for( int index = 0; index < arraySize - 1; index +=2)
                {
                    if( sharedData->vecData[index] > sharedData->vecData[index + 1] )   
                    {
                        int temp;
                        temp = sharedData->vecData[index];
                        sharedData->vecData[index] = sharedData->vecData[index+1];
                        sharedData->vecData[index+1] = temp;
                        sharedData->oddSwap = true;
                    }       
                }
                // release lock on the shared vector
                commandCheck = sem_post(&(sharedData->swapSem));
                perror("semaphore unlock");
                if (commandCheck == -1)
                {
                    perror("failed to unlock shared semaphore");
                }
            }
            else perror("failed to lock shared semaphore");
        }
        _exit(0);
    }
    else
    {
        // child.error
        // forking error.
        perror("failed to fork in child");
        exit(EXIT_FAILURE);
    }
}
else if( fork1 > 0)
{
    // original.parent
    // wait for the child process to finish.
    waitpid(fork1, NULL, 0);

}
else
{
    // forking error
    perror("failed to fork");
    exit(EXIT_FAILURE);
}

I can only guess that this has to do with how the semaphore blocks the process if a wait cannot be fulfilled, but I do not understand how perror() calls fix it.


I think your problem may be related to the way you are (not) checking that the conditions still apply after you get the semaphore, or that the checking conditions are themselves wrong.

You have:

    while(sharedData->evenSwap || sharedData->oddSwap)
    {
        // obtain lock on the shared vector
        int commandCheck = sem_wait(&(sharedData->swapSem));
        perror("semaphore lock");
        // if lock was obtained
        if (commandCheck == 0)
        {
            sharedData->oddSwap = false;

After you get the semaphore, you should probably validate that either sharedData->evenSwap or sharedData->oddSwap is still true, relinquishing the semaphore if not. This is a standard idiom; you check, lock and recheck, because the status may have changed between the original check and the time you gain the lock.

Under this hypothesis, the perror() calls alter the timing of the processes, allowing the conditions to stay unchanged for longer than when the perror() calls are not present. So, there is a timing problem here, somewhere.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜