The C API to POSIX threads requires a special flag to be set if you want to share a mutex between processes in shared memory - see sem_init()
. I don't really know what the diff is but I'm having trouble trying to use C++ std::condition_variable in shared memory - its seg faulting. I can't see anything mentioning this in the C++ docs, or the constructors. I was wondering how to / if you can use C++ thread mutex in shared memory. Here is my test code for reference. Note squeue
is just a simple (POD) static sized circular queue, and irrelevant stuff is omitted:
#include <iostream>
#include <sys/mman.h>
#include <sys/stat.h> /* For mode constants */
#include <fcntl.h> /* For O_* constants */
#include "squeue.h"
#define SHM_FILENAME "/shimmy-foo"
#define SQUEUE_LENGTH 10
typedef struct {
squeue<int,SQUEUE_LENGTH> queue;
std::mutex mutex;
std::condition_variable_any condvar;
} SHM;
int main() {
int shm_fd = 0;
SHM * shm_ptr = NULL;
squeue<int,SQUEUE_LENGTH> * queue = NULL;
std::mutex * mutex;
std::condition_variable_any * condvar;
// Init SHM. ftruncate() will zero area.
if((shm_fd = shm_open(SHM_FILENAME, O_CREAT|O_RDWR|O_EXCL, S_IREAD|S_IWRITE)) == -1 ) {
fprintf (stderr, "Could not open shm object. %s\n", strerror(errno));
return errno;
}
else {
fprintf (stderr, "Open shm OK. %d\n", shm_fd);
}
ftruncate(shm_fd, sizeof(SHM));
// Connect the shmptr pointer to set to the shared memory area,
// with desired permissions
if((shm_ptr = (SHM*)mmap(0, sizeof(SHM), PROT_READ|PROT_WRITE, MAP_SHARED, shm_fd, 0)) == MAP_FAILED) {
fprintf (stderr, "Could not map shm. %s\n", strerror(errno));
return errno;
}
else {
fprintf(stderr, "Mapped shm OK. %p\n", shm_ptr);
}
// Create queue and mutex.
queue = new(&shm_ptr->queue) squeue<int,SQUEUE_LENGTH>();
mutex = new(&shm_ptr->mutex) std::mutex();
condvar = new(&shm_ptr->condvar) std::condition_variable_any();
srand(time(NULL));
while(true) {
cout << "Waiting on lock" << endl;
mutex->lock();
if(!queue->full()) {
int value = rand()%100;
queue->push(value);
cout << "Pushed " << value << endl;
} else {
cout << "Que is full!" << endl;
};
condvar->notify_all(); //Seg fault.
mutex->unlock();
sleep(1);
}
}
I use a similar pattern, however, the standard mutex and condition variables are not designed to be shared between processes. The reason for that is that POSIX requires PTHREAD_PROCESS_SHARED
attribute set on process shared mutexes and condition variables but the standard C++ primitives do not do that. On Windows it might be more complicated than that.
You can try using boost process shared mutexes and process shared condition variables instead. Or create your own wrappers for POSIX interfaces.
It could also be that squeue
corrupts memory beyond its buffer overwriting the mutex and the condition variable that lay above in memory in struct SHM
. I would try commenting out the code that pushes into the queue and see if you still get that crash. I tried your code with queue code commented out and it works as expected.
You may also like to use condition_variable
instead of condition_variable_any
, because the latter one maintains its own mutex but that mutex is not needed if you notify that condition variable while having the associated mutex locked (as you do).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With