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

4

Решение

Предостережение: Я не провел много времени с boost::interprocess, так что эта информация просто из быстрого осмотра источника. Тем не менее, я много использовал API синхронизации Windows, так что здесь …


Основное различие между двумя методами межпроцессной синхронизации заключается в том, как объект существует в системе.

С boost::interprocess::named_mutexКак и системный мьютекс, похоже, что объект синхронизации создается как файл в системе. Расположение файла основано на записях реестра (см. Примечание 1) (по крайней мере, в Boost 1.54.0) … это более вероятный находится в папке «Общие данные приложения» (см. примечание 2). При сбое приложения этот файл в вашем случае не удаляется. Я не уверен, что это так, но в случае сбоя приложения лучше не связываться с файловой системой, так, на всякий случай.

И наоборот, когда вы используете CreateMutexобъект создается в режиме ядра, к которому для именованных мьютексов могут обращаться несколько приложений. Вы получаете дескриптор Mutex, указывая имя при его создании, и теряете дескриптор при вызове CloseHandle в теме. Объект мьютекса уничтожается, когда на него больше не ссылаются дескрипторы.

Важная часть этого в документация:

Система закрывает ручку автоматически, когда процесс завершается. Объект мьютекса уничтожается, когда его последний дескриптор был закрыт.

В основном это означает, что Windows будет очищаться после вашего приложения.

Обратите внимание, что если вы не выполните ReleaseMutexи ваше приложение владеет мьютексом, когда оно умирает, тогда возможно / вероятно, что ожидающий поток или процесс увидят, что мьютекс был оставлен (WaitForSingleObject возвращается WAIT_ABANDONED) и получит право собственности.

Я прошу прощения за то, что не предоставил решение, но я надеюсь, что это ответит на ваш вопрос о том, почему две системы действуют по-разному.


  1. Кроме того, использование записей реестра для получения этой информации ужасно — было бы безопаснее и перспективнее использовать SHGetKnownFolderPath, Но я отвлекся.

  2. В зависимости от версии вашей ОС, это может быть %ALLUSERSPROFILE%\Application Data\boost.interprocess или же ProgramData\boost.interprocessили где-то еще целиком.

6

Другие решения

то, что вы хотите, не тривиально, и interprocess_mutex определенно является неправильным способом.

то, что вы можете сделать, это удалить мьютекс при завершении, предоставив деструктор для удаления и / или в подвохе (…), но это не гарантированно сработает, поскольку этого не произойдет, если вы прекратите процесс напрямую (из ОС). также он может случайно удалить мьютекс, пока ваше приложение запускается дважды.

Один из подходов заключается в том, чтобы сохранить идентификатор процесса (например, в общей памяти) при первом запуске вашей программы и удалить его, когда он остановится. Каждый раз, когда вы запускаете приложение, читайте и проверяйте, находится ли идентификатор еще в процессе, если нет, запускайте программу.

1

По вопросам рекламы [email protected]