简体   繁体   English

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

[英]boost::interprocess::file_lock erroneous behavior when used with std::ostream

I am trying to use file_lock for restricting multiple instances of the same program running at the same time (Implementing something mentioned in this answer ).我正在尝试使用file_lock来限制同时运行的同一程序的多个实例(实现此答案中提到的内容)。 I am using 1.66 version of boost on Linux .我在Linux上使用1.66版本的 boost。

Before locking the file, I make sure that file exists (by opening it using std::ofstream with std::ios::app ).在锁定文件之前,我确保该文件存在(通过使用std::ofstreamstd::ios::app打开它)。 I noticed one thing, if we close the stream, then file_lock is automatically unlocked and hence, allowing multiple instance of the same program to run at the same time.我注意到一件事,如果我们关闭 stream,那么file_lock会自动解锁,因此允许同一程序的多个实例同时运行。

The program below doesn't work as file_lock is automatically released.下面的程序不起作用,因为 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;
}

However, the two programs below works.但是,下面的两个程序有效。

Looks like if we have opened a file while trying to acquire the file_lock, then we need to keep that file opened till we want to hold the lock.看起来如果我们在尝试获取 file_lock 时打开了一个文件,那么我们需要保持该文件处于打开状态,直到我们想要持有锁为止。 If we close the file, then lock is automatically released.如果我们关闭文件,那么锁就会自动释放。 I am not sure if this is a bug.我不确定这是否是一个错误。 Can someone help me with the reason of such behavior?有人可以帮我解释这种行为的原因吗?

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;
}

And

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;
}

I have found the reason.我找到了原因。 It was due to boost::interprocess::file_lock were implemented using Classic POSIX File-locks .这是因为boost::interprocess::file_lock是使用Classic POSIX File-locks实现的。

This link explains the issue with POSIX locks and hence, with boost file_locks.这个链接解释了 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.正是这个细节让大多数程序员大吃一惊,因为它要求程序在确定可以删除该文件上的锁之前不要关闭文件描述符。

Looks like I should be either using flock or some other platform library which uses flock .看起来我应该使用flock或其他使用flock的平台库。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM