Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Equivalent of Windows's named mutex in Mac OS X? [duplicate]

Currently I'm porting a software from Windows to Mac OS X in C++.

In Windows, there's an abandoned state in global named mutex which means that current owner process of the mutex is gone without releasing the mutex. (It will likely be caused by application crash)

Because of abandoned state exists, trying to lock for abandoned mutex will not cause deadlock.
If there's no abandoned state, it will wait forever for a mutex which is not owned by anyone.

There's another approach by using timeout to assume the mutex is abandoned if unable to obtain the mutex for certain time, but it is not a perfect solution compared against abandoned mutex way. In the worst case, accidentally two processes can access to the object locked by the mutex.

Is there any mutex support abandoned state in Mac OS X/Linux?

I researched for the boost library, the boost library has a named mutex, but that one is based on a shared file so it does not have abandoned state.

Please give me some advise.

like image 846
Aki24x Avatar asked May 28 '14 19:05

Aki24x


1 Answers

Well maybe a little late but you can use the pthread_mutexattr_t to set your mutex attribute to be shared between pthread_mutexattr_setpshared(&mutexAttr, PTHREAD_PROCESS_SHARED); API. This mutex value needs to be shared between processes by storing it into a named shared memory.

Here is a code snippet:

int key = ftok(NAMED_MEMORY, ID_TAG);
if (-1 == key)
{
    printf("Unable to name shared memory\n");
    exit(1);
}

// Create the segment exclusively (if the segment already exists then a combination of IPC_CREAT | IPC_EXCL returns an error EEXIST)
int m_iShmid = shmget(key, TOTAL_SIZE, READ_WRITE_PERMISSIONS | IPC_CREAT | IPC_EXCL);
if (m_iShmid < 0)
{
    if (EEXIST == errno)
    {
        // if the shared memory already exists we only fetch the id to that memory
        m_iShmid = shmget(key, TOTAL_SIZE, READ_WRITE_PERMISSIONS);
    }
    if (m_iShmid < 0)
    {
        printf("Unable to create shared memory - %s\n",strerror(errno));
        exit(1);
    }
    else
        printf("Attached to the existing shared memory\n");
}
else
    printf("Created new shared memory\n");

// Now we attach the segment to our data space.
mutex = reinterpret_cast<pthread_mutex_t*>(shmat(m_iShmid, NULL, 0));
if (reinterpret_cast<pthread_mutex_t*>(-1) ==  mutex)
{
    printf("Unable to attach shared memory to the process - %s\n",strerror(errno));
    exit(1);
}

// Now we can set this mutex to be shared between processes
pthread_mutex_t* mutex;
pthread_mutexattr_t mutexAttr;
ret = pthread_mutexattr_init(&mutexAttr);
if(ret != 0)
{
    printf("pthread_mutexattr_init failed - err=%d\n",ret);
    exit(1);
}
ret = pthread_mutexattr_setpshared(&mutexAttr, PTHREAD_PROCESS_SHARED);
if(ret != 0)
{
    printf("pthread_mutexattr_setpshared failed - err=%d\n",ret);
    exit(1);
}
ret = pthread_mutexattr_setrobust_np(&mutexAttr, PTHREAD_MUTEX_ROBUST_NP);
if(ret != 0)
{
    printf("pthread_mutexattr_setrobust_np failed - err=%d\n",ret);
    exit(1);
}
ret = pthread_mutex_init(mutex, &mutexAttr);
if(ret != 0)
{
    printf("pthread_mutex_init failed - err=%d\n",ret);
    exit(1);
}
// ------ Use the mutex from here on between processes
like image 96
seaborg Avatar answered Sep 29 '22 00:09

seaborg