【问题标题】:What constitutes asynchronous-safeness什么构成异步安全
【发布时间】:2012-01-19 13:19:52
【问题描述】:

据说你应该只在信号处理程序中调用异步安全函数。我的问题是,什么是异步安全可重入线程安全的函数是异步安全我猜?还是不行?

【问题讨论】:

  • 找到this。因此,似乎函数可能不使用全局变量(除了原子类型),并且在任何时候中断它都应该使进程保持一致状态。
  • 我会说是可重入的,而不是访问线程本地的东西。如果您访问线程本地的东西,您将与您将中断的线程竞争,并可能导致数据损坏。

标签: c linux asynchronous synchronization signal-handling


【解决方案1】:

重入和线程安全与此无关或无关。这些功能的副作用、状态和中断是重要的事实。

asynchronous-safe function [GNU Pth]

函数是异步安全的, 或异步信号安全,如果它可以被安全地调用并且没有 信号处理程序上下文中的副作用。也就是说,它必须是 能够在任何时候被打断以线性地乱序运行 不会导致不一致的状态。它还必须正常运行 当全局数据本身可能处于不一致状态时。一些 此处列出了异步安全操作:

  • 调用signal() 函数重新安装信号处理程序
  • 无条件修改volatile sig_atomic_t变量(如 对这种类型的修改是原子的)
  • 调用_Exit()函数 立即终止程序执行
  • 调用异步安全 函数,由您的实现指定

很少有函数是 可移植的异步安全。如果一个函数执行任何其他 操作,它可能不是可移植的异步安全的。

经验法则是这样的 - 仅从信号处理程序发出某些条件变量的信号(例如 futex/pthread 条件、唤醒 epoll 循环等)。

更新:

正如 EmployedRussian 所建议的,即使调用 pthread_cond_signal 也是一个坏主意。我检查了最近的eglibc 的源代码,里面有锁定/解锁对。因此,引入了死锁的可能性。这使我们几乎没有选择向其他线程发出信号:

  1. 使用eventfd
  2. 更改全局原子变量并希望 SA_RESTART 未设置,其他线程将检查我们的原子变量。

【讨论】:

  • guaranteed to be async-signal-safe by POSIX.1-2008 的函数列表要大得多(您必须向下滚动查看列表),包括大多数传统的 Unix“系统调用”和访问到errno。此外,如果您知道只有在sigsuspend 上阻止正常执行时才会调用信号处理程序,那么在处理程序中执行任意操作是安全的。
  • pthread_* 函数都不是异步信号安全的,因此“信号 pthread 条件变量”是一个不好的建议 (TM)。
  • @EmployedRussian:并不是说它不安全,它可能只是不会唤醒等待 POSIX 条件变量的人。
  • @EmployedRussian:实际上,我收回我的话——刚刚检查了源代码,它也可能导致死锁:-) 所以我想唯一安全的唤醒是通过 fcntl 和/或原子变量.
  • 从信号处理程序唤醒select 风格的主循环的常用技巧是将一个字节写入感兴趣的 fds 集中的管道。 signalfd 也可能感兴趣。
【解决方案2】:

对于您自己的代码,是的,可重入和线程安全是您需要的特性,因为根据您设置信号处理机制的方式,您的信号处理程序本身可能会被另一个信号中断。一般来说,尽量在信号处理程序中做尽可能少的工作。设置标志以在您的正常程序流程中触发特殊代码可能就是您应该做的所有事情。

对于操作系统中您可能调用的函数,请查看man 7 signal 以获取可以安全调用的列表。请注意,malloc()free() 不在列表中。 pthread 同步 API 也不在列表中,但我认为有些调用必须是安全的,因此您可以在信号处理程序中安全地设置全局标志。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-22
    • 2017-12-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多