【问题标题】:ThreadSanitizer: signal handler spoils errno - how to avoid set of errnoThreadSanitizer:信号处理程序破坏 errno - 如何避免设置 errno
【发布时间】:2018-12-06 15:13:07
【问题描述】:

我有一些处理 POSIX 信号的代码,作为它的一部分(为了信号安全) - 执行 sem_post() 系统调用(根据http://man7.org/linux/man-pages/man3/sem_post.3.html'async signal safe')。

但是当我运行这段代码时——我偶尔会收到线程清理程序的投诉:

总结:ThreadSanitizer:信号处理程序破坏了 Stroika::Foundation::Execution 中的 errno /home/lewis/Sandbox/Stroika-Build-Dir-Ubuntu1804_x86_64/Library/Sources/Stroika/Foundation/Execution/SignalHandlers.cpp:497: :SignalHandlerRegistry::FirstPassSignalHandler_(int)

我相信这是由于对 sem_post 的调用,它可能确实会覆盖 errno。

是的 - 如果它发生在正确的(错误的?)时间,这确实会弄乱另一个线程。

我一直发现'thread local' errno 机制是一种处理错误的便捷方式,但我现在才意识到它对于信号处理代码有多么危险。

有什么方法可以调用系统调用而不覆盖 errno?至少可以隐约携带的东西?

即使http://man7.org/linux/man-pages/man2/syscall.2.html - 表示它会将结果存储在 errno 中。

【问题讨论】:

    标签: multithreading thread-safety posix


    【解决方案1】:

    在 Linux 上,您可以使用 _syscall。 另一种方法是在信号处理程序的开头保存 errno 并在返回之前恢复。 如果您确定您的函数在这方面是安全的,您还可以使用一些属性(在 GCC 和 CLANG 中)来禁用函数检测。

    【讨论】:

    • 根据man7.org/linux/man-pages/man2/_syscall.2.html - 从内核 2.6.18 开始,_syscall 宏已从提供给用户空间的头文件中删除。改用 syscall(2) (并且从未在 x64 上工作过)。
    • 另外,保存和恢复仍将是 errno 的竞争/覆盖。
    • errno 是线程安全的,信号处理程序在处理信号的线程的上下文(相同的内核,甚至相同的缓存)中执行,因此保存/恢复变得不活泼。
    • 谢谢!我没有想到那部分(当信号处理程序正在运行时线程不是)。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2018-06-30
    • 1970-01-01
    • 1970-01-01
    • 2012-11-08
    • 2012-07-26
    • 2013-11-22
    • 2014-08-25
    • 1970-01-01
    相关资源
    最近更新 更多