什么会导致抛出异常 16:“mutex: Resource busy”(使用 Boost / BB10)?

2024-01-14

我已将一个用 C++ 和 Boost 编写的长期稳定的库移植到 Blackberry 10。该库在设备之间传输文件。该库编译和链接良好,并且运行良好。但是,在传输 1、2 或 3 个文件后,我的 Blackberry 10 设备上总是会遇到抛出异常。在源代码中将异常捕获为 boost::system::system_error 显示它是异常 16,并显示文本“mutex: Resource busy”。

下面是发生异常的源码:

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

跟踪日志行是:

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

异常在上面的“start”和“end”注释之间的某个位置抛出,其中定义了 boost::asio::io_service 对象。我在 StackOverflow、Google 等上搜索了与“互斥体:资源繁忙”相关的任何内容,但一无所获。我的代码此时未访问任何应用程序级互斥体,因此我假设所引用的互斥体是与 Boost 相关的互斥体。

有人可以告诉我该消息的基本含义是什么,以及为什么会抛出“资源繁忙”异常? Blackberry 10 上是否存在与该异常相关的已知问题?

提前致谢!


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

执行摘要

pthread_mutex_init () 在 55-65 后抛出异常增强::互斥体构造函数调用,因为具有 boost::mutex 作为成员变量的应用程序级派生类对象未完全析构,因为基类析构函数是非虚拟的。这导致 boost::mutex-s 的数量不断增加,直到抛出互斥异常。当派生类的析构函数被正确调用时,将不再引发互斥异常。

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

(1) 一个早期的理论被提出,系统中存在太多的互斥体,并且应用程序超出了允许的同步对象最大数量的一些未知限制(尽管QNX文档明确指出此类对象的数量是无限的)。为了测试这一点,我们修改了增强::互斥体班级来自:

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

to:

class 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 网站三个月前发布的内容 http://lists.freebsd.org/pipermail/freebsd-threads/2013-May/005422.html与我们的症状非常相似:

我遇到了似乎无法解决的麻烦。我的节目 重复地创建和销毁互斥体(并且,显然,将它们用于 之间)。在创建第 60 个锁时,我总是得到 ENOMEM。我有 空闲内存,很多。所有锁都可以正确释放。

不幸的是,这条线索并没有为我们指明建设性的方向。

(4) 当仔细研究应用程序的代码时,发现派生对象的基类析构函数是非虚拟的,从而泄漏了一些内存,从而取得了突破。将基类析构函数设为虚拟修复了内存泄漏并解决了互斥异常。

(5) 即使在将基类的析构函数设为虚拟之后,我们发现在使用 QNX® Momentics 工具套件编译 Blackberry 10 时,派生类的析构函数并未被调用。我们通过指定基础来“解决”这个问题和导出的析构函数作为虚拟的。然后派生的析构函数才被调用。这可能表明 QNX 编译器的 C++ 规范实现中存在错误,该规范明确指出虚拟性传播到派生类 (工作草案,编程语言 C++ 标准 (2012),第 250 页,脚注 9 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf).

编辑:参见这个堆栈溢出帖子 https://stackoverflow.com/questions/35132860/my-qnx-bb10-c-application-crashes-a-simple-c-object-seems-to-be-corrupted/35132861#35132861QNX 在虚拟析构函数方面失败的另一个例子。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

什么会导致抛出异常 16:“mutex: Resource busy”(使用 Boost / BB10)? 的相关文章

  • 对静态成员变量的未定义引用

    我有一个有静态成员的类 它也是我的程序中其他几个类的基类 这是它的头文件 ifndef YARL OBJECT HPP define YARL OBJECT HPP namespace yarlObject class YarlObject
  • Linux 使用 boost asio 拒绝套接字绑定权限

    我在绑定套接字时遇到问题 并且以用户身份运行程序时权限被拒绝 这行代码会产生错误 acceptor new boost asio ip tcp acceptor io boost asio ip tcp endpoint boost asi
  • MySql 最后插入 ID,连接器 .net

    我正在使用 MySql Connector net 我需要获取最后一个查询生成的插入 id 现在 我假设返回值是MySqlHelper ExecuteNonQuery应该是最后一个插入id 但它只返回1 我正在使用的代码是 int inse
  • 使用 JSON 格式正确配置 NLog 到 IHostBuilder

    我有以下代码 应该接受 NLog 的 JSON appsettings 配置 然后使用它来创建 NLog LogFactory 这个 NLog 工厂应该被传递到 MyService 类中 以便在那里创建一个记录器 class Program
  • 无缝滚动瓷砖地图

    我正在开发一个自上而下的角色扮演游戏 并且想要实现无缝滚动地图 也就是说 当玩家探索世界时 地图之间没有加载屏幕 也没有通往下一个区域的 门 我有两种方法可以打破世界 在顶层 我有 区域 它只是 9 个 地图 的集合 这些区域仅由目录表示
  • 使用 size_t 值反向遍历向量

    我想以相反的方向遍历向量的值 如您所知 向量的大小为 size t 当我使用以下代码时 for size t r m size 1 r gt 0 r x r f r for size t c r 1 c lt m size c x r m
  • 读取STM32 MCU SPI数据寄存器的值

    有很多类似的问题 但似乎没有一个问题完全相同 我正在将 STML4 MCU 连接到 6 轴传感器 LSM6DS3 我已经成功地在 I2C 中实现了所有内容 但想要 SPI 的额外速度 和 DMA 如果我能让这些第一步工作起来的话 因此 第一
  • Qt QML 数据模型似乎不适用于 C++

    我一直在使用中的示例http doc qt digia com 4 7 qdeclarativemodels html http doc qt digia com 4 7 qdeclarativemodels html这是 QML 声明性数
  • 捕获另一个进程未处理的异常

    我想知道我是否可以捕获我开始使用 Process Start 的另一个进程抛出的未处理的异常 我知道我可以用这个捕获标准错误link http social msdn microsoft com Forums en US csharpgen
  • C++ 错误:从“char”到“const char*”的转换无效

    我对 C 完全陌生 我创建了这个函数 bool guessWord string compWord cout lt lt Guess a letter string userLetter cin gt gt userLetter for u
  • 带双重检查锁的单例设计模式

    假设您有以下代码 1 为什么我们使用双重检查锁 为什么单锁不够好 请提供详细的例子 2 这种实施方式的主要缺点是什么 我该如何证明呢 Thanks public sealed class SomeSingleton5 private sta
  • 使用 QGraphicsScene 实现流畅的动画

    我希望我的问题并不总是同样的问题 我有一个 QGraphicsScene 它的项目是一些 QGraphicsPixmap 我用一个计时器来移动它们 每秒 SetX 10 我设置 10是因为窗口大100 使用这个解决方案我的动画不流畅 我想我
  • 按值返回的函数的返回语句中的初始化

    我的问题源于深入研究std move in return语句 例如以下示例 struct A A std cout lt lt Constructed lt lt this lt lt std endl A A noexcept std c
  • 为什么《Scala 中的函数式编程》一书的“无异常处理错误”一章中没有提到“scala.util.Try”?

    在 Scala 中的函数式编程 一书中的 无异常处理错误 一章中 作者给出 从函数体抛出异常的问题 Use Option如果我们不关心实际的异常 Use Either如果我们关心实际的异常 But scala util Try没有提到 从我
  • 数组与映射的性能

    我必须循环一个大数组中的元素子集 其中每个元素都指向另一个元素 问题来自于检测大图中的连接组件 我的算法如下 1 考虑第一个元素 2 将下一个元素视为前一个元素所指向的元素 3 循环直到没有发现新元素 4 考虑1 3中尚未考虑的下一个元素
  • 如何解决内存碎片

    我们偶尔会遇到这样的问题 长时间运行的服务器进程 在 Windows Server 2003 上运行 由于内存分配失败而引发异常 我们怀疑这些分配由于内存碎片而失败 因此 我们一直在寻找一些可能对我们有帮助的替代内存分配机制 我希望有人能告
  • char* argv[] 在 c/c++ 中如何工作? [复制]

    这个问题在这里已经有答案了 我知道它用于使用命令行中的参数 但我没有得到声明 字符 argv 它是否意味着指向 char 数组的指针 如果是的话为什么没有大小 如果不是动态数组 就不需要有大小吗 我做了一些研究 发现有人说它会衰减为 cha
  • 从 exit() 和 fork() 返回的结果奇怪地发生了位移

    我有一个 C 代码 有时会自行分叉 每个分叉都会执行一些操作 然后返回一个错误代码 目前 每个子进程返回其 ID 0 n void other int numero exit numero int main for int i 0 i lt
  • 从 STL 列表中删除项目

    我想创建一个函数 如果符合特定条件 则将项目从一个 STL 列表移动到另一个列表 这段代码不是这样做的方法 迭代器很可能会被擦除 函数失效并导致问题 for std list
  • 如何在没有 Visual Studio 的情况下将新文件添加到 .csproj 文件

    如何添加新文件到 csproj从命令提示符 我认为没有任何工具可以响应命令行上的 add project 命令来执行此操作 但我认为您可以幸运地创建一个程序 脚本来直接操作 csproj 文件的 XML 内容 csproj 文件的结构如下所

随机推荐