ОБНОВЛЕНИЕ 21.02.2020: Удержание блокировки во время уведомления на самом деле не помогает. Как я понимаю, переменная условия остается недействительной в общей памяти в результате процесса ожидания.
Итак, у меня есть это приложение, использующее промежуточный процесс boost для совместного использования памяти, и доступ к нему синхронизируется с использованием условия межпроцессного процесса. переменная. Я использую повышение 1.62 на Windows. Я компилирую с использованием Microsoft Windows Build Tools 2015.
Что происходит, когда я завершаю процесс ожидания с помощью Ctrl- C, процесс уведомления застревает в вызове notify.
Вот демонстрационная программа, которая позволяет воспроизвести проблему. Вы должны запустить исполняемый файл один раз без каких-либо аргументов, чтобы запустить процесс ожидания, и еще раз с некоторым аргументом, чтобы запустить процесс уведомления. Тогда убей первый процесс. Иногда вы заметите, что печать останавливается на «Входящем уведомлении».
#include <boost/interprocess/shared_memory_object.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <boost/interprocess/sync/interprocess_mutex.hpp>
#include <boost/interprocess/sync/interprocess_condition.hpp>
#include <iostream>
struct shared_data
{
boost::interprocess::interprocess_mutex mutex;
boost::interprocess::interprocess_condition condition;
bool test_bool = false;
};
int main(int argc, char *argv[])
{
using namespace boost::interprocess;
if (argc == 1) {
struct shm_remove
{
shm_remove() {
shared_memory_object::remove("MySharedMemory");
}
~shm_remove() {
shared_memory_object::remove("MySharedMemory");
}
} remover;
shared_memory_object shm(create_only, "MySharedMemory", read_write);
shm.truncate(sizeof(shared_data));
mapped_region region(shm, read_write);
void* addr = region.get_address();
shared_data* data = new (addr) shared_data;
while (true) {
scoped_lock<interprocess_mutex> lock(data->mutex);
while (!data->test_bool) {
data->condition.wait(lock);
}
std::cout << "test_bool became true" << std::endl;
data->test_bool = false;
}
}
else {
shared_memory_object shm(open_only, "MySharedMemory", read_write);
mapped_region region(shm, read_write);
shared_data* data = static_cast<shared_data*>(region.get_address());
while (true) {
{
scoped_lock<interprocess_mutex> lock(data->mutex);
data->test_bool = true;
}
std::cout << "Entering notify" << std::endl;
data->condition.notify_one();
std::cout << "Exiting notify" << std::endl;
}
}
}
(Конечно, убийство во время ожидания - хар sh, но я, насколько я отлаживал, ожидание вызова очищается после сигнала)
Если я сохраню полученную блокировку при вызове notify_one, проблема не проявляется. Тем не менее, я ожидал, что не будет необходимости сохранять блокировку, полученную при уведомлении, в духе реализации многопоточности c ++. Я не нашел никакой спецификации по этому вопросу в документации, только пример , который действительно сохраняет полученную блокировку.
Теперь, учитывая, что у меня есть решение моей проблемы, мои вопросы:
- Требуется ли получить блокировку при уведомлении об ожидаемом и единственно правильном использовании, или это ошибка?
- Если это ожидаемое использование, почему ?