代码之家  ›  专栏  ›  技术社区  ›  abhiarora

当与std::ostream一起使用时,boost::interprocess::file_lock错误行为

  •  0
  • abhiarora  · 技术社区  · 4 年前

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

    在锁定文件之前,我确保该文件存在(通过使用以下命令打开它 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时打开了一个文件,那么我们需要保持该文件打开,直到我们想要持有锁为止。如果我们关闭文件,则锁会自动释放。我不确定这是不是一个bug。有人能帮我解释一下这种行为的原因吗?

    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;
    }
    
    0 回复  |  直到 3 年前
        1
  •  2
  •   abhiarora    4 年前

    我找到了原因。这是由于 boost::interprocess::file_lock 使用 Classic POSIX File-locks .

    这个 link 解释了POSIX锁的问题,因此也解释了boost-file_locks的问题。

    更令人不安的是,该标准规定,当进程关闭与锁定文件对应的任何文件描述符时,进程持有的所有锁都会被丢弃,即使这些锁是使用仍然打开的文件描述符创建的。正是这个细节让大多数程序员感到惊讶,因为它要求程序格外小心,在确定可以删除文件上的锁之前,不要关闭文件描述符。

    看起来我应该使用 flock 或使用的其他平台库 flock .

    推荐文章