[英]Using boost::interprocess::named_mutex correctly
我在使用 named_mutex 時遇到問題,我試圖用它來確定我的應用程序的另一個實例是否正在運行。
我定義了一個全局變量:
named_mutex dssMutex{ open_or_create, "DeepSkyStacker.Mutex.UniqueID.12354687" };
然后在 main() 中我寫道:
if (!dssMutex.try_lock()) firstInstance = false;
在 main() 的末尾,在我完成了所有捕獲的事情之后:
dssMutex.unlock();
我遇到的問題是,當這是我的程序在系統中的唯一實例時(剛重啟后),try_lock() 返回 false。 我還在調試日志中看到了這一點(這可能只是 try_lock() 的產物):
Exception thrown at 0x00007FFB838C4FD9 in DeepSkyStacker.exe: Microsoft C++ exception: boost::interprocess::interprocess_exception at memory location 0x00007FF5FFF7EF00.
那我做錯了什么?
謝謝大衛
三件事:
try_lock
返回 false,你不應該unlock
;scoped_lock
幫助器更容易除非未處理,否則顯示的異常應該不是問題。 如果您使用的是 Visual Studio,則可以將調試器配置為在拋出或未處理的異常時中斷。 對該消息最好的解釋是它是在內部處理的。 最糟糕的解釋是你沒有處理它。 在那種情況下,它會解釋鎖沒有被釋放。
請注意,異常可能是由於try_lock
失敗后嘗試unlock
引起的?
以下是我將如何使用延遲作用域鎖來實現異常安全:
#include <boost/interprocess/sync/named_mutex.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <iostream>
#include <thread>
namespace bip = boost::interprocess;
using namespace std::chrono_literals;
int main(int, char** argv) {
bip::named_mutex dssMutex{bip::open_or_create, "UniqueID.12354687"};
bip::scoped_lock<bip::named_mutex> lk(dssMutex, bip::defer_lock);
bool const firstInstance = lk.try_lock();
std::cout << argv[0] << (firstInstance?" FRIST!":" SECOND") << std::flush;
std::this_thread::sleep_for(1s);
std::cout << " Bye\n" << std::flush;
}
Coliru無法處理它,但這是在本地執行的操作:
現在,如前所述,這仍然不夠健壯,但是您可以通過至少處理例如 SIGINT 來使其不那么糟糕(當您在終端中按 Ctrl-C 時,POSIX 會發生什么):
#include <boost/asio.hpp>
#include <boost/interprocess/sync/named_mutex.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
#include <iostream>
#include <thread>
namespace bip = boost::interprocess;
using namespace std::chrono_literals;
int main(int, char** argv) {
boost::asio::thread_pool ioc(1);
boost::asio::signal_set ss(ioc, SIGINT, SIGTERM);
ss.async_wait([](auto ec, int s) {
if (ec == boost::asio::error::operation_aborted)
return;
std::cerr << "signal " << s << " (" << ec.message() << ")" << std::endl;
});
bip::named_mutex dssMutex{bip::open_or_create, "UniqueID.12354687"};
bip::scoped_lock<bip::named_mutex> lk(dssMutex, bip::defer_lock);
bool const firstInstance = lk.try_lock();
std::cout << argv[0] << (firstInstance?" FRIST!":" SECOND") << std::flush;
std::this_thread::sleep_for(1s);
std::cout << " Bye\n" << std::flush;
ss.cancel();
ioc.join();
}
現在可以中斷進程了:
for a in {1..10}; do sleep "0.$RANDOM"; ./one; done&
for a in {1..10}; do sleep "0.$RANDOM"; ./two; done&
sleep 3; pkill -INT -f ./one;
sleep 5; pkill -INT -f ./two
如果仔細觀察,處理程序現在實際上沒有執行任何操作。 很可能你想確保它干凈地關閉main
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.