Во-первых, указатель, который указывает на interprocess_mutex
, выделенный в общей памяти, нельзя уничтожить с помощью delete
напрямую, поскольку указатель указывает на некоторый адрес в адресном пространстве процесса, который отображает в область общей памяти, где фактически находится мьютекс.Поэтому в следующем коде выполнение строки delete mtx
дает сбой.
#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 *****
}
Чтобы правильно уничтожить созданный объект с помощью указателя, вызовите shm.destroy_ptr(mtx)
вместо delete mtx
.
Во-вторых, скомпилировав следующий код и выполнив его дважды на двух отдельных консолях, можно проверить, что уничтожение interprocess_mutex
с помощью destroy_ptr
, пока другой процесс блокирует мьютекс, не приводит к сбою.Кроме того, процесс, удерживающий блокировку, может безопасно разблокировать мьютекс впоследствии без сбоев.(Проверено на 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
}