linux - 如何确保信号处理程序永远不会屈服于同一进程组中的线程?

标签 linux multithreading signals glibc nptl

这是一个元问题,因为我认为我有一个适合我的解决方案,但它也有其缺点和缺点。我需要做一个相当普通的事情,在一个线程上捕获SIGSEGV(没有专用的崩溃处理线程),转储一些调试信息并退出。

这里要了解的事实是,崩溃时,我的应用程序运行llvm-symbolizer会花一些时间(相对而言)并导致产生结果(由于clone + execve或超出线程的时间量),我已经看到后者在自己进行符号化时发生使用libLLVM进行处理)。进行所有这些操作的原因是获得具有脱字符符号和行/文件信息(存储在单独的DWP文件中)的堆栈跟踪。出于明显的原因,我不希望在SIGSEGV处理程序上发生任何事情,因为我打算在应用程序(线程组)执行后终止它,并且永远不要从信号处理程序中返回。

尽管我不了解Linux信号处理以及glibc的包装器对它们的处理能力,但我并不了解基本的陷阱,但是关于信号处理的具体细节并没有太多信息,例如同步信号处理程序是否获得任何特殊的优先级在调度方面。

集思广益,我有一些想法和缺点:

  • pthread_kill(<every other thread>, SIGSTOP)-具有更多线程的笨拙功能,可与信号处理程序进行交互,这似乎可能具有意外的副作用。还需要拦截其他库中的线程创建,以跟踪线程列表,并在每次系统调用时增加抢占的机会。一旦它们停下来指向syscall exit stub 或完全使用SIGKILL,甚至可能更改其上下文。
  • 全局标志,用作所有线程的取消点(有点像pthread_cancel/pthread_testcancel)。更安全,但需要大量维护,并且在整个代码库中,除了会产生轻微的性能开销外,还有些麻烦。全局标志还可能导致错误级联,因为该程序已经处于不可预测的状态,因此让任何其他线程在那里运行已经不是很大。
  • “滥用”调度程序,这是我目前的选择,我的实现是答案之一。切换到FIFO调度策略并提高优先级,因此成为该组中唯一可运行的线程。
  • Core转储不是一个选项,因为这里的目标是首先避免它们。我宁愿除符号程序外也不需要辅助程序。

  • 环境是具有glibc的典型的基于NPTL的Linux(4.4)发行版。

    我知道崩溃处理程序现在相当普遍,因此我相信我选择的方法都不是那么好,尤其是考虑到我从未见过调度程序“hack”曾经被这种方式使用过。因此,有没有人比调度程序“hack”更好,更清洁,风险更低的替代品,我是否在我对信号的一般想法中遗漏了任何要点?

    编辑:似乎我并没有真正考虑过MP(根据注释),也没有在MP情况下其他线程仍可运行并且可以愉快地继续在其他处理器上与FIFO线程一起运行的事实。但是,我可以将进程的亲和力更改为仅在与崩溃线程相同的内核上执行,这基本上将在时间表边界有效冻结所有其他线程。但是,这仍然保留了“由于阻塞IO而导致的FIFO线程屈服”的情况。

    似乎FIFO + SIGSTOP选项是最好的选择,尽管我确实想知道是否还有其他技巧可以使线程无法使用SIGSTOP来安排。从文档上看,似乎不可能将线程的CPU亲和力设置为零(将其置于技术上可运行的边缘状态,除非没有可用的处理器可运行)。

    最佳答案

    upon crash, my application runs llvm-symbolizer



    这很可能导致死锁。我找不到关于llvm-symbolizer是异步信号安全的任何声明。很可能会调用malloc,如果这样的话,如果崩溃也发生在malloc内部(例如,由于其他地方的堆损坏),则肯定会死锁。

    Switching to FIFO scheduling policy and raising priority therefore becoming the only runnable thread in that group.



    我相信您错了:只要SCHED_FIFO线程是可运行的,它将一直运行(即不会发出任何阻塞的系统调用)。如果该线程确实发出了这样的调用(必须这样做:例如,用单独的open文件.dwp),它将阻塞并且其他线程将变为可运行状态。

    TL; DR:没有简单的方法可以实现您想要的目标,而且无论如何似乎都是不必要的:您在乎什么,当崩溃的线程完成其业务时,其他线程继续运行?

    关于linux - 如何确保信号处理程序永远不会屈服于同一进程组中的线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49958057/

    相关文章:

    linux - 如何使用 i2cget 从 i2c 读取数据?

    多线程上的困惑

    来自相机的 Python OpenCV 流 - 多线程,时间戳

    exception - Linux中除以零异常处理

    makefile - 如何在 GNU make 中捕获错误和中断?

    linux - 猫重定向自动杀死?

    linux - 如何从命令提示符发送电子邮件?

    c - 使用 libusb 输出不正确

    linux - 如何将图像转换为低宽度 200

    Java Swing 长线程执行