boost::interprocess::file_lock 与 std::ostream 一起使用时的错误行为
boost::interprocess::file_lock erroneous behavior when used with std::ostream
我正在尝试使用 file_lock for restricting multiple instances of the same program running at the same time (Implementing something mentioned in this answer)。我在 Linux
.
上使用 1.66
版本的 boost
在锁定文件之前,我确保该文件存在(通过使用 std::ofstream
和 std::ios::app
打开它)。我注意到一件事,如果我们关闭流,那么 file_lock
会自动解锁,因此允许同一程序的多个实例同时 运行。
下面的程序无法运行,因为file_lock是自动发布的。
int main(int argc, char *argv[])
{
namespace bipc = boost::interprocess;
if (argc < 2)
return 0;
std::string path = argv[1];
std::string lock_path = "/var/lock/" + path + ".lock";
std::ofstream stream(lock_path, std::ios::app);
bipc::file_lock lock(lock_path.c_str());
if (!lock.try_lock())
throw std::runtime_error("Multiple instance");
std::cout << "Running" << std::endl;
stream.close();
while (true)
std::this_thread::sleep_for(std::chrono::seconds(1));
return 0;
}
但是,下面的两个程序有效。
看起来如果我们在尝试获取 file_lock 时打开了一个文件,那么我们需要保持该文件打开直到我们想要持有锁。如果我们关闭文件,那么锁会自动释放。我不确定这是否是一个错误。有人可以帮助我了解这种行为的原因吗?
int main(int argc, char *argv[])
{
namespace bipc = boost::interprocess;
if (argc < 2)
return 0;
std::string path = argv[1];
std::string lock_path = "/var/lock/" + path + ".lock";
std::ofstream stream(lock_path, std::ios::app);
bipc::file_lock lock(lock_path.c_str());
if (!lock.try_lock())
throw std::runtime_error("Multiple instance");
std::cout << "Running" << std::endl;
while (true)
std::this_thread::sleep_for(std::chrono::seconds(1));
return 0;
}
和
int main(int argc, char *argv[])
{
namespace bipc = boost::interprocess;
if (argc < 2)
return 0;
std::string path = argv[1];
std::string lock_path = "/var/lock/" + path + ".lock";
{
std::ofstream stream(lock_path, std::ios::app);
}
bipc::file_lock lock(lock_path.c_str());
if (!lock.try_lock())
throw std::runtime_error("Multiple instance");
std::cout << "Running" << std::endl;
while (true)
std::this_thread::sleep_for(std::chrono::seconds(1));
return 0;
}
我找到原因了。这是因为 boost::interprocess::file_lock
是使用 Classic POSIX File-locks
实现的。
此 link 解释了 POSIX 锁的问题,因此也解释了 boost file_locks 的问题。
More troublingly, the standard states that all locks held by a process are dropped any time the process closes any file descriptor that corresponds to the locked file, even if those locks were made using a still-open file descriptor. It is this detail that catches most programmers by surprise as it requires that a program take extra care not to close a file descriptor until it is certain that locks held on that file are able to be dropped.
看来我应该使用 flock 或其他使用 flock
.
的平台库
我正在尝试使用 file_lock for restricting multiple instances of the same program running at the same time (Implementing something mentioned in this answer)。我在 Linux
.
1.66
版本的 boost
在锁定文件之前,我确保该文件存在(通过使用 std::ofstream
和 std::ios::app
打开它)。我注意到一件事,如果我们关闭流,那么 file_lock
会自动解锁,因此允许同一程序的多个实例同时 运行。
下面的程序无法运行,因为file_lock是自动发布的。
int main(int argc, char *argv[])
{
namespace bipc = boost::interprocess;
if (argc < 2)
return 0;
std::string path = argv[1];
std::string lock_path = "/var/lock/" + path + ".lock";
std::ofstream stream(lock_path, std::ios::app);
bipc::file_lock lock(lock_path.c_str());
if (!lock.try_lock())
throw std::runtime_error("Multiple instance");
std::cout << "Running" << std::endl;
stream.close();
while (true)
std::this_thread::sleep_for(std::chrono::seconds(1));
return 0;
}
但是,下面的两个程序有效。
看起来如果我们在尝试获取 file_lock 时打开了一个文件,那么我们需要保持该文件打开直到我们想要持有锁。如果我们关闭文件,那么锁会自动释放。我不确定这是否是一个错误。有人可以帮助我了解这种行为的原因吗?
int main(int argc, char *argv[])
{
namespace bipc = boost::interprocess;
if (argc < 2)
return 0;
std::string path = argv[1];
std::string lock_path = "/var/lock/" + path + ".lock";
std::ofstream stream(lock_path, std::ios::app);
bipc::file_lock lock(lock_path.c_str());
if (!lock.try_lock())
throw std::runtime_error("Multiple instance");
std::cout << "Running" << std::endl;
while (true)
std::this_thread::sleep_for(std::chrono::seconds(1));
return 0;
}
和
int main(int argc, char *argv[])
{
namespace bipc = boost::interprocess;
if (argc < 2)
return 0;
std::string path = argv[1];
std::string lock_path = "/var/lock/" + path + ".lock";
{
std::ofstream stream(lock_path, std::ios::app);
}
bipc::file_lock lock(lock_path.c_str());
if (!lock.try_lock())
throw std::runtime_error("Multiple instance");
std::cout << "Running" << std::endl;
while (true)
std::this_thread::sleep_for(std::chrono::seconds(1));
return 0;
}
我找到原因了。这是因为 boost::interprocess::file_lock
是使用 Classic POSIX File-locks
实现的。
此 link 解释了 POSIX 锁的问题,因此也解释了 boost file_locks 的问题。
More troublingly, the standard states that all locks held by a process are dropped any time the process closes any file descriptor that corresponds to the locked file, even if those locks were made using a still-open file descriptor. It is this detail that catches most programmers by surprise as it requires that a program take extra care not to close a file descriptor until it is certain that locks held on that file are able to be dropped.
看来我应该使用 flock 或其他使用 flock
.