什么可能导致异常16:“mutex:资源占用”被抛出(使用Boost / BB10)? [英] What can cause an exception 16: "mutex: Resource busy" to be thrown (using Boost / BB10)?

查看:294
本文介绍了什么可能导致异常16:“mutex:资源占用”被抛出(使用Boost / BB10)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经将一个长期工作的稳定库用C ++和Boost写入Blackberry 10.库在设备之间传输文件。图书馆汇编和链接良好,运行良好。但是,在传输1,2或3个文件后,我一直遇到黑莓10设备上抛出的异常。在源代码中作为boost :: system :: system_error捕获异常,显示为异常16,文本为mutex:资源繁忙。



这里是发生异常的源代码:

  try 
{
。 。 。

//查找操作ID的DtpFunctionData,使用它来调用处理函数
std :: map< int,FunctionData> :: iterator iter = _vecFunctionData.find(operationId);
if(iter == _vecDtpClientFunctionData.end())
return EC_GENERAL_FAILURE;

HANDLINGFUNC_1 handlingFunc =(* iter).second._clientHandlingFunc;
POSTOPFUNC_1 postOpFunc =(* iter).second._clientPostOpFunc;
bool callPostOpOnSuccess =(* iter).second._callPostOpOnSuccess;

//打开一个与远程对等体的TcpPortListener相对的套接字
/ *开始:----- EXCEPTION 16:mutex:资源繁忙----- * /
boost :: asio :: io_service io_service;
/ *结束:----- EXCEPTION 16:mutex:资源繁忙----- * /

boost :: asio :: ip :: tcp :: socket socket(io_service);
。 。 。
}
catch(boost :: system :: system_error& err)
{
LOGLINE((error,Boost exception(%d / \%s \\)抓到HandleQueueOperation,err.code().value(),err.what()));
返回EC_EXCEPTION_CAUGHT;
}

跟踪日志行是:

  18:37:04(149077264)[error]在HandleQueueOperation中捕获的Boost异常(16 /mutex:资源繁忙)

异常被抛出上面的开始和结束注释之间,其中定义了boost :: asio :: io_service对象。我搜索了StackOverflow,Google等与mutex:资源繁忙有关的任何内容,但没有发现任何内容。我的代码在这一点上没有访问任何应用级别的互斥体,所以我认为引用的互斥体是一个Boost相关的。



有人可以告诉我什么消息基本上意味着为什么资源繁忙异常被抛出?有没有一个已知的问题在黑莓10相关的例外?



提前感谢!

解决方案

经过多次调试,同事终于解决了这个问题。



执行摘要



由于应用程序级派生类对象具有boost :: mutex作为成员,因此在55-65 :: mutex 构造函数调用之后pthread_mutex_init()抛出异常变量,没有被完全破坏,因为基类析构函数是非虚拟的。这导致boost :: mutex-s的数量上升,直到引发了互斥异常。当派生类的析构函数被正确地调用时,不再抛出异常异常。



沿路收集的相关/有趣事实

(1)提出了一个早期理论,系统中存在太多的互斥体,应用程序超出了对允许的最大同步对象数量的一些未知限制(尽管QNX文档清楚地说明这样的对象的数量是无限制的)。为了测试这个,我们修改了 boost :: mutex 类:

  class mutex 
{
private:
。 。 。
public:
mutex()
{
。 。 。
}
〜mutex()
{
。 。 。
}
}

to:

 类mutex 
{
private:
static int _nCount;
public:
mutex()
{
++ _ nCount;
。 。 。
}
〜mutex()
{
。 。 。
--_ nCount;
}
static int getCount()
{
return _nCount;
}
。 。 。
}

请注意,访问_nCount变量不同步(我们需要一个互斥对象为此!),但是从应用程序调用调试调试功能boost :: mutex :: getCount()函数使我们有信心在异常时互斥量的数量很少(55平均为-65个活跃互斥体)。



通过添加静态访问功能,监控最低级别的对象(例如,Boost中的互斥体)的这种技术是一个很好的工具调试粘性问题时请考虑。



(2)我们偶尔收到一个ENOMEM异常,表明存在内存问题(系统无法分配创建所需的资源互斥体)。



(3)从三个月前发布的FreeBSD网站与我们的症状非常相似:


我是havi烦恼我似乎无法解决。我的程序
可重复地创建并破坏互斥体(并且显然在
之间使用它们)。围绕第60个锁创建,我总是得到ENOMEM。我有
的免费内存,很多。所有锁都可以正常释放。


不幸的是,线程没有指向我们建设性的方向。


$ (4)当仔细研究应用程序的代码找到一个派生对象的基类析构函数是非虚拟的,从而泄漏一些内存时,突破就来了。 (5)即使在基类的析构函数虚拟化之后,我们发现派生类的析构函数是使用QNX®Momentics工具套件编译Blackberry 10时不会被调用。我们通过将基础和派生的析构函数指定为虚拟来黑客这个问题。只有这样才能得到派生的析构函数。这可能表明QNX编译器执行C ++规范时出现错误,该错误明确指出虚拟传播到派生类(工作草案,编程语言C ++(2012),第250页,脚注9 )。



编辑:请参阅此堆叠溢出帖子为QNX放弃关于虚拟析构函数的另一个例子。


I've ported a long-working stable library written in C++ and Boost to Blackberry 10. The library transfers files between devices. The library compiles and links well, and runs just fine. However, I consistently encounter a thrown exception on my Blackberry 10 device after 1, 2, or 3 files have been transferred. Catching the exception as a boost::system::system_error in the source code shows it is exception 16, with a text of "mutex: Resource busy".

Here is the source code where the exception occurs:

try
{
    . . .

    // Find DtpFunctionData for the operation ID, use it to invoke handling function
    std::map<int, FunctionData>::iterator iter = _vecFunctionData.find (operationId);
    if (iter == _vecDtpClientFunctionData.end ())
        return EC_GENERAL_FAILURE;

    HANDLINGFUNC_1 handlingFunc = (*iter).second._clientHandlingFunc;
    POSTOPFUNC_1 postOpFunc = (*iter).second._clientPostOpFunc;
    bool callPostOpOnSuccess = (*iter).second._callPostOpOnSuccess;

    // Open a socket opposite the remote peer's TcpPortListener
    /* Start: ----- EXCEPTION 16: "mutex: Resource busy" ----- */
    boost::asio::io_service io_service;
    /* End: ----- EXCEPTION 16: "mutex: Resource busy" ----- */

    boost::asio::ip::tcp::socket socket (io_service);
    . . .
}
catch (boost::system::system_error& err)
{
    LOGLINE (("error", "Boost exception (%d / \"%s\") caught in HandleQueueOperation",  err.code ().value(), err.what()));
       return EC_EXCEPTION_CAUGHT;
}

The trace log line is:

18:37:04 ( 149077264) [error] Boost exception (16 / "mutex: Resource busy") caught in HandleQueueOperation

The exception is thrown somewhere between the "start" and "end" comments above, where the boost::asio::io_service object is defined. I've searched StackOverflow, Google, etc. for anything related to "mutex: Resource busy" but have found nothing. My code is not accessing any app-level mutexes at this point, so I assume the mutex referred to is a Boost-related one.

Can someone tell me what the message basically means, and why the "resource busy" exception is being thrown? Is there a known issue on Blackberry 10 related to the exception?

Thanks in advance!

解决方案

After much debugging a colleague finally solved the problem.

Executive summary

The exception was being thrown by pthread_mutex_init () after 55-65 boost::mutex constructor invocations because an application-level derived class object, having a boost::mutex as a member variable, was not fully destructed because the base class destructor was non-virtual. This caused the number of boost::mutex-s to rise until the mutex exception was thrown. When the derived class's destructor was correctly invoked the mutex exceptions were no longer thrown.

Relevant / interesting facts gleaned along the way

(1) An early theory was put forward that there were too many mutexes in the system and the application was exceeding some unknown restriction on the maximum number of synchronization objects allowed (although the QNX documentation clearly states the number of such objects is unlimited). To test this we modified the boost::mutex class from:

class mutex
{
private:
    . . .
public:
    mutex()
    {
        . . .
    }
    ~mutex()
    {
        . . .
    }
}

to:

class mutex
{
private:
    static int _nCount;
public:
    mutex()
    {
        ++_nCount;
        . . .
    }
    ~mutex()
    {
        . . .
        --_nCount;
    }
    static int getCount ()
    {
        return _nCount;
    }
    . . .
}

Note that access to the _nCount variable is not synchronized (we'd need a mutex object for this!), but calling the debugging boost::mutex::getCount() function from the application gave us the confidence that the number of mutexes was low at the time of the exception (55-65 active mutexes on average).

This technique of monitoring an object at the lowest level (e.g., mutexes within Boost) by adding static access functions is a good tool to consider when debugging sticky problems.

(2) We occasionally received an ENOMEM exception, indicating a memory problem ("the system cannot allocate the resources required to create the mutex").

(3) A FreeBSD site posting from three months ago was remarkably similar to our symptoms:

I'm having troubles that I seem unable to resolve. My programs creates and destroys mutexes repeatably (and, obviously, uses them in between). Around the 60th lock created, I always get ENOMEM. I have free memory, lots of it. All locks get released properly.

Unfortunately the thread did not point us in a constructive direction.

(4) The breakthrough came when careful studying of the application's code found a derived object whose base class destructor was non-virtual, thereby leaking some memory. Making the base class destructor virtual fixed the memory leak and solved the mutex exceptions.

(5) Even after making the base class's destructor virtual we found that the derived class's destructor was not being called when compiling for Blackberry 10 using the QNX® Momentics Tool Suite. We "hacked" this problem by specifying both the base and the derived destructors as virtual. Only then did the derived destructor get called. This may indicate an error in the QNX compiler's implementation of the C++ specification which states clearly that virtual-ness propagates to derived classes (Working Draft, Standard for Programming Language C++ (2012), page 250, footnote 9).

Edit: See this Stack Overflow post for another example of QNX's dropping the ball regarding virtual destructors.

这篇关于什么可能导致异常16:“mutex:资源占用”被抛出(使用Boost / BB10)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆