摘要

我展示了一个代码示例,它重现了我的软件中存在的一个非常奇怪的错误。它使用 Boost 创建 3 个命名信号量,并在单个线程中等待每个信号量。这有效。但是,如果我更改信号量的名称(通过添加给定的前缀),则不会:第三个信号量无缘无故地等待无限时间。

详细信息(源代码和行为)

#include <string>
#include <vector>
#include <iostream>
#include <boost/thread.hpp>
#include <boost/date_time.hpp>
#include <boost/interprocess/sync/named_semaphore.hpp>

struct Lock
{
    std::string name;
    unsigned int count;
    Lock(const std::string& name_, unsigned int count_) : name(name_), count(count_) {}
};

int main()
{
    std::vector<Lock> locks;
    locks.push_back(Lock("Sleep1", 1));
    locks.push_back(Lock("Hello", 1));
    locks.push_back(Lock("Sleep2", 1));

    for(std::size_t i = 0; i < locks.size(); ++i)
    {
        {
            const std::string sem_name = locks[i].name;
            const unsigned int sem_count = locks[i].count;
            std::cout << "Open or Create semaphore (" << sem_name << ", " << sem_count << ")" << std::endl;
            boost::interprocess::named_semaphore semaphore(boost::interprocess::open_or_create, sem_name.c_str(), sem_count);
            std::cout << "Wait..." << std::flush;
            semaphore.wait();
            std::cout << " DONE" << std::endl;
        }
        boost::this_thread::sleep(boost::posix_time::seconds(5));
        {
            const std::string sem_name = locks[i].name;
            std::cout << "Open semaphore (" << sem_name << ")" << std::endl;
            boost::interprocess::named_semaphore semaphore(boost::interprocess::open_only, sem_name.c_str());
            std::cout << "Post..." << std::flush;
            semaphore.post();
            std::cout << " DONE" << std::endl;
        }
    }

    return 0;
}

执行此示例,我得到以下(预期)输出:
> ./sem
Open or Create semaphore (Sleep1, 1)
Wait... DONE
Open semaphore (Sleep1)
Post... DONE
Open or Create semaphore (Hello, 1)
Wait... DONE
Open semaphore (Hello)
Post... DONE
Open or Create semaphore (Sleep2, 1)
Wait... DONE
Open semaphore (Sleep2)
Post... DONE

如果我将定义信号量名称的行替换为以下内容:
std::vector<Lock> locks;
locks.push_back(Lock("CHAIN_EVALUATOR_Sleep1", 1));
locks.push_back(Lock("CHAIN_EVALUATOR_Hello", 1));
locks.push_back(Lock("CHAIN_EVALUATOR_Sleep2", 1));

执行不会以以下输出终止:
Open or Create semaphore (CHAIN_EVALUATOR_Sleep1, 1)
Wait... DONE
Open semaphore (CHAIN_EVALUATOR_Sleep1)
Post... DONE
Open or Create semaphore (CHAIN_EVALUATOR_Hello, 1)
Wait... DONE
Open semaphore (CHAIN_EVALUATOR_Hello)
Post... DONE
Open or Create semaphore (CHAIN_EVALUATOR_Sleep2, 1)
Wait...

请注意新名称的奇怪选择。实际上,它失败了。 FOO_BAR_FOO_BAR_Sleep1FOOBAR_FOOBAR_Sleep1 都不会失败。它看起来很奇怪,我想我没有正确使用它并且我处于随机行为......

配置
  • Linux openSUSE 42.1
  • GCC 4.8.5
  • Boost 1.64.0(包括 Boost.Python
    使用 python 2.7.9)

  • 编译行
    g++ test_semaphore.cpp -o sem \
    -I /softs/boost/1.64.0/python/2.7.9/64/gcc/4.8.5/include \
    /softs/boost/1.64.0/python/2.7.9/64/gcc/4.8.5/lib/libboost_date_time-mt.a \
    /softs/boost/1.64.0/python/2.7.9/64/gcc/4.8.5/lib/libboost_thread-mt.a \
    /softs/boost/1.64.0/python/2.7.9/64/gcc/4.8.5/lib/libboost_system-mt.a \
    -l pthread
    

    注意: 出于兼容性原因,我不使用 C++11。

    最佳答案

    Named semaphors in boost are implying Kernel or Filesystem persistence 因此,当您传递 open_or_create 时,可能存在具有指定名称的命名信号量(可能来自先前中断的启动?),在这种情况下,sem_count 将被忽略,并且信号量将处于其保留的任何状态。尝试在创建之前调用 named_semaphore::remove或传递 create_only 标志。

    关于c++ - 我的信号量(来自Boost的named_semaphore)有什么问题?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46276634/

    10-16 20:44