在c++中,进程获得SIGABRT的场景是什么?这个信号总是来自进程内部还是可以从一个进程发送到另一个进程?

有没有办法确定是哪个进程在发送这个信号?


当前回答

正如“@sarnold”,恰当地指出,任何进程都可以向任何其他进程发送信号,因此,一个进程可以向其他进程发送SIGABORT,在这种情况下,接收进程无法区分它是否因为自己的内存调整等而到来,或者其他人已经“unicastly”发送给它。

在我工作的一个系统中,有一个死锁检测器,它实际上可以通过心跳来检测进程是否从某些任务中出来。如果不是,则声明该进程处于死锁状态,并向其发送SIGABORT。

我只是想分享这一前景参考问题。

其他回答

GNU libc将在调用abort()(然后触发SIGABRT)之前将有关一些致命条件的信息打印到/dev/tty,但是如果您将程序作为服务运行,或者不是在真正的终端窗口中运行,那么这些消息可能会丢失,因为没有tty来显示这些消息。

请参阅我关于将libc重定向到stderr而不是/dev/tty的帖子:

捕捉libc错误消息,从/dev/tty重定向

libc和其他库通常使用SIGABRT在出现严重错误时中止程序。例如,glibc在检测到double-free或其他堆损坏时发送SIGABRT。

此外,大多数断言实现在断言失败的情况下使用SIGABRT。

此外,SIGABRT可以像其他信号一样从任何其他进程发送。当然,发送进程需要以相同的用户或根用户运行。

关于第一个问题:在c++中进程获得SIGABRT的场景是什么?

我可以想到两种c++程序自动中止的特殊情况——不是通过直接调用std::abort()或std::terminate():

一:在处理异常时抛出异常。

try {
    throw "abc";
}
catch (...) {
    throw "def";  // abort here
}

二:试图在main()外部传播的未捕获异常。

int main(int argc, char** argv)
{
    throw "abc";  // abort here
}

c++专家可能还能举出更多的特殊情况。

在这些参考页面上也有很多好的信息:

https://en.cppreference.com/w/cpp/utility/program/abort https://en.cppreference.com/w/cpp/error/terminate

你可以使用kill(2)接口向任何进程发送任何信号:

杀死 -SIGABRT 30823

30823是我启动的一个破折号进程,所以我可以很容易地找到我想要终止的进程。

$ /bin/dash
$ Aborted

Aborted输出显然是dash报告SIGABRT的方式。

它可以使用kill(2)直接发送给任何进程,或者进程可以通过assert(3)、abort(3)或raise(3)将信号发送给自己。

在我的例子中,这是由于在一个数组中输入的一个索引等于数组的长度。

string x[5];

for(int i=1; i<=5; i++){

    cin>>x[i];

}

X[5]正在被访问,但不存在。