【问题标题】:Glib hash table issues with signal handling code信号处理代码的 Glib 哈希表问题
【发布时间】:2012-05-03 17:33:28
【问题描述】:

我有一些系统级代码,它会每隔一段时间触发一次计时器,并且有一个信号处理程序在这些信号到达时对其进行管理。这工作正常,似乎完全合理。主程序旁边还有两个单独的线程运行,但它们不共享任何变量,而是使用 glib 的异步队列仅向一个方向传递消息。

相同的代码使用 glib 的 GHashTable 来存储键/值对。当信号代码被注释出系统时,哈希表似乎运行良好。然而,当它被启用时,会出现一个奇怪的竞争条件,其中对 g_hash_table_lookup 的调用实际上返回 NULL(这意味着没有用于查找它的键的条目),而实际上该条目确实存在(是的,我通过使用g_hash_table_foreach 打印整个键/值对列表来确保。为什么大多数时候会出现这种情况? GLib 的哈希表实现有问题吗?有时查找调用是成功的。

这是一个非常特殊的情况,如果它没有意义,我可以进一步澄清,但我希望我做错了什么,以便实际上可以解决这个问题。

更多信息:不在信号处理程序范围内但访问 g_hash_table 变量的代码段被信号阻塞调用包围,因此信号处理程序在进程最初访问它们时也不会访问这些变量。

【问题讨论】:

  • 当您说“相同的代码...”时,您的意思是信号处理程序本身正在使用 GHashTable API?还是只是并行线程?
  • 是的,信号处理程序使用 g_hash_table_remove()。
  • 您可能不应该在信号处理程序中进行哈希表工作;检查signal(7) 以获取可以在信号处理程序中调用的安全函数列表,并为相当短的列表做好准备。
  • 天哪,这永远不会可靠地工作。
  • @emish 你正处于一个充满伤害的世界,我的朋友。

标签: c thread-safety system signals glib


【解决方案1】:

一般来说,信号处理器只能设置标志和进行系统调用

碰巧的是,ISO C 对信号处理程序可以做什么有严格的限制,并且大多数库入口点和大多数 API 甚至不是远程 100% 多线程安全的,其中大约 0.0% 是信号处理程序-安全的。也就是说,绝对禁止从信号处理程序调用几乎任何东西。

特别是对于 GHashTable,g_hash_table_ref()g_hash_table_unref() 是仅有的甚至是线程安全的 API 元素,它们都不是信号处理程序安全的。实际上,ISO-C 只允许信号处理程序修改用volatile sig_atomic_t 声明的对象,并且只能调用几个库例程。

我们中的一些人认为线程系统本质上是危险的,实际上是细微错误的放射源。一个开始担心的好地方是The Problem with Threads.(请注意,信号处理程序本身要糟糕得多。没有人认为那里的 API 是安全的......)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多