boost::interprocess::named_mutex против CreateMutex
Я хочу переключиться с CreatMutex
в boost::interprocess::named_mutex
ограничить мое приложение одним экземпляром. Оба метода работают, когда приложение работает и заканчивается нормально. Тем не менее, блокировка не снимается при сбое приложения и использовании boost::interprocess::named_mutex
, Я мог бы решить эту проблему, используя два name_mutex, но я не совсем понимаю проблему.
Почему замок для boost::interprocess::named_mutex
не выпускается при сбое приложения, но оно выпускается с CreatMutex
? Какая разница?
boost::interprocess::named_mutex mutex(boost::interprocess::open_or_create, "my_mutex");
boost::interprocess::scoped_lock<boost::interprocess::named_mutex> lock(mutex, boost::interprocess::try_to_lock);
if(!lock) {
return 1; //exit
}
//application may crash here.
boost::interprocess::named_mutex::remove("my_mutex");
return 1; //exit
2 ответа
Предостережение: я не провел много времени с boost::interprocess
, так что эта информация просто из быстрого осмотра источника. Тем не менее, я много использовал API синхронизации Windows, так что здесь...
Основное различие между двумя методами межпроцессной синхронизации заключается в том, как объект существует в системе.
С boost::interprocess::named_mutex
Как и системный мьютекс, похоже, что объект синхронизации создается как файл в системе. Расположение файла основано на записях реестра (см. Примечание 1) (по крайней мере, в Boost 1.54.0)... скорее всего, оно находится в папке "Общие данные приложения" (см. Примечание 2). При сбое приложения этот файл в вашем случае не удаляется. Я не уверен, что это так, но в случае сбоя приложения лучше не связываться с файловой системой, на всякий случай.
И наоборот, когда вы используете CreateMutex
объект создается в режиме ядра, к которому для именованных мьютексов могут обращаться несколько приложений. Вы получаете дескриптор Mutex, указав имя при его создании, и теряете дескриптор при вызове CloseHandle
в теме. Объект мьютекса уничтожается, когда на него больше не ссылаются дескрипторы.
Важная часть этого находится в документации:
Система закрывает ручку автоматически, когда процесс завершается. Объект мьютекса уничтожается, когда его последний дескриптор был закрыт.
Это в основном означает, что Windows будет очищаться после вашего приложения.
Обратите внимание, что если вы не выполните ReleaseMutex
и ваше приложение владеет мьютексом, когда оно умирает, тогда возможно / вероятно, что ожидающий поток или процесс увидят, что мьютекс был оставлен (WaitForSingleObject
возвращается WAIT_ABANDONED
) и получит право собственности.
Я прошу прощения за то, что не предоставил решение, но я надеюсь, что это ответит на ваш вопрос о том, почему две системы действуют по-разному.
Кроме того, использование записей реестра для получения этой информации ужасно - было бы безопаснее и перспективнее использовать
SHGetKnownFolderPath
, Но я отвлекся.В зависимости от версии вашей ОС, это может быть
%ALLUSERSPROFILE%\Application Data\boost.interprocess
или жеProgramData\boost.interprocess
или где-то еще целиком.
То, что вы хотите, не является тривиальным, и interprocess_mutex определенно является неправильным способом.
то, что вы могли бы сделать, это удалить мьютекс при завершении, предоставив деструктор для удаления и / или в подвохе (...), но это не гарантированно сработает, поскольку этого не произойдет, если вы прекратите процесс напрямую (из ОС). также он может случайно удалить мьютекс, пока ваше приложение запускается дважды.
Один из подходов заключается в том, чтобы сохранить идентификатор процесса (например, в общей памяти) при первом запуске вашей программы и удалить его при остановке. Каждый раз, когда вы запускаете приложение, читайте и проверяйте, все ли идентификатор еще обрабатывается, если нет, запускайте программу.