Boost作用域锁定断言失败

时间:2014-10-08 17:01:38

标签: c++ multithreading boost

我在Linux应用程序中使用Boost 1.41,它在一个线程上接收数据并将其粘贴到队列中,另一个线程将其从队列中弹出并处理它。为了使线程安全,我使用了范围锁。

我的问题是,很少有锁定功能在读取功能中失败,并显示消息:

void boost :: mutex :: lock()断言'!pthread_mutext_lock(& m)'失败

这种情况非常罕见,在最后一次运行中,失败前需要36小时(~4.25M交易)。下面列出了读写函数,它始终位于Assert出现的读取函数中

写入队列

 void PacketForwarder::Enqueue(const byte_string& newPacket, long sequenceId)
 {
    try
    {
        boost::mutex::scoped_lock theScopedLock(pktQueueLock);
        queueItem itm(newPacket,sequenceId);
        packetQueue.push(itm);

        if (IsConnecting() && packetQueue.size() > MaximumQueueSize)
        {
            // Reached maximum queue size while client unavailable; popping.
            packetQueue.pop();
        }
    }
    catch(...)
    {
        std::cout << name << " Exception was caught:" << std::endl;
    }
 }

从队列中读取

while ( shouldRun )
{
    try
    {
        if (clientSetsHaveChanged)
        {
            tryConnect();
        }

        size_t size = packetQueue.size();
        if (size > 0)
        {
            byte_string packet;
            boost::mutex::scoped_lock theQLock(pktQueueLock);
            queueItem itm = packetQueue.front();
            packet = itm.data;
            packetQueue.pop();

            BytesSent += packet.size();

            trySend(packet);   
        }
        else
        {
            boost::this_thread::sleep(boost::posix_time::milliseconds(50));
        }
    }
    catch (...)
    {
        cout << name << " Other exception in send packet" << endl;
    }

我用Google搜索并在销毁scoped_locks时发现了一些问题,但没有得到锁定。我还搜索了发布说明和Trac日志,看看是否已被其他人识别为问题。我认为我的代码就像它得到的一样简单,但显然有些东西已经出现了。有什么想法吗? TIA 保罗

1 个答案:

答案 0 :(得分:0)

您的程序中存在一个线程安全问题,在这段代码中:

    size_t size = packetQueue.size();
    if (size > 0)
    {
        byte_string packet;
        boost::mutex::scoped_lock theQLock(pktQueueLock);
        queueItem itm = packetQueue.front();
        packet = itm.data;
        packetQueue.pop();
        // ...
    }

这里的问题是,在您检查队列大小的时间和获得锁定的时间之间,其他一些读者线程可能会将最后一项从队列中取出,这将导致front()和{{1} } 失败。除非你只有一个读者线程,否则你也需要进行大小检查。

我不知道这是否是断言失败的原因。断言意味着对pop()的调用返回了一个非零值,表示错误。不幸的是,Boost没有显示possible pthread_mutex_lock errors究竟发生了什么。