c++ - boost::interprocess::file_lock 与 std::ostream 一起使用时的错误行为

标签 c++ linux boost boost-interprocess filelock

我正在尝试使用file_lock用于限制同一程序的多个实例同时运行(实现 this answer 中提到的内容)。我在 Linux 上使用 1.66 版本的 boost。

在锁定文件之前,我确保该文件存在(通过使用 std::ofstreamstd::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的平台库。

关于c++ - boost::interprocess::file_lock 与 std::ostream 一起使用时的错误行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61950886/

相关文章:

linux - need_resched 信息(linux 内核 2.6.30)

c - 用我自己的 close() 函数替换 Linux 中的 close() 函数

c++ - 为什么编译器会在某些优化级别警告未初始化的边迭代器?

c++ - 为什么我的程序在读取/写入文件时丢掉最重要的数字?

c++ - 如何在 Visual C++ 2013 上递归删除二叉树?

c++ - 有什么方法可以避免手动包装基类的方法以将它们标记为 Q_INVOKABLE?

c++ - boost 库更新后模板函数调用不起作用

c++ - 具有不存在的线程 ID 的 OpenThread

Linux "echo -n"未被刷新

c++ - 如何在 unordered_map 的键中使用 std::tr1::function 对象?