我想为sigsegv、sigill和其他一些可能的信号设置一个信号处理程序,这些信号不是终止整个进程,而是终止有问题的线程,并可能在某个地方设置一个标志,以便监视线程可以投诉并启动另一个线程。我不确定是否有安全的方法来做这件事。p螺纹似乎提供了退出当前线程的功能,以及取消另一个线程,但是这些潜在调用了一组在退出处理程序。即使他们不这样做,似乎有许多情况下,他们不异步信号安全,虽然有可能,这些情况是可以避免的。有没有一个低级函数我可以调用它来破坏线程?假设我以异步信号安全的方式修改自己的数据结构,并且不获取互斥量,那么是否存在pthread/其他全局数据结构,这些结构可能仅仅由在sigsegv处终止的线程而处于不一致的状态?我想到了malloc,但是malloc本身不应该sigsegv/sigill,除非libc是bug。我意识到POSIX在这里非常保守,没有任何保证。只要有办法在实践中做到这一点,我就很高兴。顺便说一句,叉子不是一个选择。
最佳答案
如果SIGSEGV
/SIGILL
/etc发生在您自己的代码中,则信号处理程序将不会在异步信号上下文中运行(它基本上是同步信号,但如果发生在标准库函数中,则仍然是a s上下文),因此您可以从信号处理程序合法调用pthread_exit
。然而,仍有一些问题使这种做法值得怀疑:SIGSEGV
/SIGILL
/etc.除非通过raise
、kill
、pthread_kill
、sigqueue
、free
等方式生成,否则不会在定义了行为的程序中发生(在某些特殊情况下,它们将是异步信号)。否则,它们表示程序具有未定义的行为。如果程序调用了未定义的行为,则所有下注都将关闭。ub在时间上不与特定线程或特定序列隔离。如果程序有ub,那么它的整个输出/行为就没有意义。
如果程序的状态已损坏(例如,由于-malloc
之后的访问、使用无效指针、缓冲区溢出等),则很可能第一次错误访问将发生在标准库的一部分(例如,pthread_exit
内部)而不是代码中。在这种情况下,信号处理程序在安全上下文中运行,不能调用。当然程序已经有ub了(见上面的一点),但是即使你想假装这不是问题,你还是会有麻烦的。
如果您的程序遇到此类崩溃,您需要找到原因并修复它,而不是尝试用信号处理程序修补它。瓦尔格林是你的朋友。如果这是不可能的,最好的办法是将崩溃的代码隔离到单独的进程中,在这些进程中,您可以对它们异步崩溃时发生的情况进行推理,而不是将崩溃的代码放在同一进程中(在同一进程中,对代码行为的任何进一步推理一旦知道它崩溃就无效)。