Firstly, the pointer that points to an interprocess_mutex
allocated on a shared memory can't be destroyed with delete
directly, since the pointer points to some address in the process' address space that maps to the shared memory region where the mutex is actually located. Therefore, in the following code, executing the line delete mtx
crashes.
#include <boost/interprocess/managed_windows_shared_memory.hpp>
using namespace boost::interprocess;
int main()
{
managed_windows_shared_memory shm{ open_or_create, "shm", 1024 };
interprocess_mutex *mtx = shm.find_or_construct<interprocess_mutex>("gMutex")();
delete mtx; // ***** CRASH *****
}
To correctly destroy the created object via pointer, call shm.destroy_ptr(mtx)
instead of delete mtx
.
Secondly, by compiling the following code and running it twice on two separate consoles, it can be checked that destroying interprocess_mutex
with destroy_ptr
while other process is locking the mutex does not crash. Also, the process holding the lock can safely unlock the mutex afterwards without crashing. (Tested on Windows 10, Boost 1.60.0, Visual Studio 2015)
#include <boost/interprocess/sync/interprocess_semaphore.hpp>
#include <boost/interprocess/managed_windows_shared_memory.hpp>
using namespace boost::interprocess;
typedef managed_windows_shared_memory smem_t;
typedef interprocess_mutex mutex_t;
typedef interprocess_semaphore sema_t;
void first_process(smem_t *shm);
void second_process(smem_t *shm);
int main()
{
smem_t *shm = nullptr;
try {
// launching this program for the first time
// successfully creates a shared memory region
shm = new smem_t{ create_only, "shm", 1024 };
first_process(shm);
} catch (interprocess_exception& e) {
// launching this program again, it fails to create shared memory
// since it already exists
second_process(shm);
}
return EXIT_SUCCESS;
}
void first_process(smem_t *shm)
{
mutex_t *mtx = shm->find_or_construct<mutex_t>("gMutex")();
sema_t *sema1 = shm->find_or_construct<sema_t>("gSema1")(0);
sema_t *sema2 = shm->find_or_construct<sema_t>("gSema2")(0);
sema1->wait(); // wait until the second process locks the mutex
shm->destroy_ptr(mtx); // destroy the mutex, doesn't crash (delete mtx crashes)
sema2->post(); // signal the second process to unlock the mutex
}
void second_process(smem_t *shm)
{
try {
shm = new smem_t{ open_only, "shm" };
} catch (std::exception& e) {
exit(EXIT_FAILURE);
}
mutex_t *mtx = shm->find_or_construct<mutex_t>("gMutex")();
sema_t *sema1 = shm->find_or_construct<sema_t>("gSema1")(0);
sema_t *sema2 = shm->find_or_construct<sema_t>("gSema2")(0);
mtx->lock();
sema1->post(); // signal the first process that the mutex is locked
sema2->wait(); // wait until the first process calls destroy_ptr
mtx->unlock(); // doesn't crash
}