Using Pthread Mutex Shared Between Processes Correctly

Using pthread mutex shared between processes correctly

Am I right that the pthread_mutex_init doesn't provide any safe approach to initialize the pthread_mutex_t simultaneously from different processes?

Correct. It is up to you to ensure that only one process calls pthread_mutex_init() on the mutex, and that no process tries to operate on the mutex until that call has successfully returned.

For example, with POSIX shm_open() shared memory regions, you can have the processes try to open the region with the O_CREAT and O_EXCL flags, so that exactly one process will succeed in creating it. This process is then responsible for resizing the shared memory region and initialising the mutex with pthread_mutex_init(). The other processes must then wait for some kind of notification from the initialising process before opening the shared memory region - eg you could have the processes block opening a FIFO O_RDONLY, and have the initialising process notify them by opening the FIFO O_WRONLY (which will cause the open to succeed).

Usually, a shared memory segment will not be the only communication channel between the processes. Typically you would bootstrap the communication through a UNIX domain socket and negotiate the setup of the shared memory region over it, probably even passing the shared memory region file descriptor through the socket with a SCM_RIGHTS message. The shared memory region would then be used to accelerate the performance-sensitive IPC.

Share condition variable & mutex between processes: does mutex have to locked before?

To be shareable between processes a mutex needs to be initialised accordingly via a properly initialised attribute: http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutexattr_setpshared.html

#include <pthread.h>

...

pthread_mutex_t * pmutex = NULL;
pthread_mutexattr_t attrmutex;

/* Initialise attribute to mutex. */
pthread_mutexattr_init(&attrmutex);
pthread_mutexattr_setpshared(&attrmutex, PTHREAD_PROCESS_SHARED);

/* Allocate memory to pmutex here. */

/* Initialise mutex. */
pthread_mutex_init(pmutex, &attrmutex);

/* Use the mutex. */

/* Clean up. */
pthread_mutex_destroy(pmutex);
pthread_mutexattr_destroy(&attrmutex);

(error checking left out for the sake of this example's readability)

The same applies to a condition variable which should be shared between processes: http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_condattr_setpshared.html

#include <pthread.h>

...

pthread_cond_t * pcond = NULL;
pthread_condattr_t attrcond;

/* Initialise attribute to condition. */
pthread_condattr_init(&attrcond);
pthread_condattr_setpshared(&attrcond, PTHREAD_PROCESS_SHARED);

/* Allocate memory to pcond here. */

/* Initialise condition. */
pthread_cond_init(pcond, &attrcond);

/* Use the condition. */

/* Clean up. */
pthread_cond_destroy(pcond);
pthread_condattr_destroy(&attrcond);

(error checking left out for the sake of this example's readability)


Also see this answer: https://stackoverflow.com/a/2390670/694576

Interprocess mutex with pthreads

Use a POSIX semaphore initialized to 1 instead. (See below) Use sem_init for unnamed semaphores or sem_open for named ones.

sem_t sem;

/* initialize using sem_init or sem_open */

sem_wait(&sem);
/* critical region */
sem_post(&sem);

Many years after initially posting this answer, it has to be updated.

Mutexes should actually be used instead of semaphores. R and kuga's comments (copied verbatim below) explain why. In particular I find kuga's mention that mutexes can only be posted by their locking thread most compelling.


R

sem_init requires a nonzero pshared argument to be shared, just like a
mutex would require the pshared attribute. There's no reason to prefer
semaphores over mutexes for this, and in fact mutexes would be better
because you could use a robust mutex which allows you to handle the
(very real!) case where one process dies while holding the lock.

kuga

Additionally to R..`s post, a mutex can only be posted by the thread
that locks it. This is often required and a semaphore does not provide
this feature. So this is not the correct answer, Jeff´s answer should
be flagged as the correct answer.

Is it safe to share synchronization primitives between processes via shared memory?

The answer turns out to be yes. POSIX doesn't require it to be safe to use mutexes through shared memory, but it works on Linux. To be safe, one has to set the PTHREAD_PROCESS_SHARED attribute through the pthread_mutexattr_setpshared function when creating a lock or condition variable. This explicitly indicates you want any thread to be able to work on the lock, even through shared memory.



Related Topics



Leave a reply



Submit