简体   繁体   English

在SIGABRT c ++信号后继续运行程序

[英]Keep running the program after SIGABRT c++ signal

I use a third library in my c++ program which under certain circumstances emits SIGABRT signal. 我在我的c ++程序中使用了第三个库,在某些情况下该库会发出SIGABRT信号。 I know that trying to free non-initialized pointer or something like this can be the cause of this signal. 我知道尝试释放未初始化的指针或类似的东西可能是此信号的原因。 Nevertheless I want to keep running my program after this signal is emitted, to show a message and allow the user to change the settings, in order to cope with this signal. 不过,我想在此信号发出后继续运行我的程序,以显示一条消息并允许用户更改设置,以应对该信号。
(I use QT for developing.) (我使用QT进行开发。)

How can I do that? 我怎样才能做到这一点?

I use a third library in my c++ program which under certain circumstances emits SIGABRT signal 我在我的C ++程序中使用了第三个库,在某些情况下该库会发出SIGABRT信号

If you have the source code of that library, you need to correct the bug (and the bug could be in your code). 如果您拥有该库的源代码,则需要更正该错误(该错误可能在您的代码中)。

BTW, probably SIGABRT happens because abort(3) gets indirectly called (perhaps because you violated some conventions or invariants of that library, which might use assert(3) - and indirectly call abort ). 顺便说一句,可能是SIGABRT发生是因为间接调用了abort(3) (也许是因为您违反了该库的某些约定或不变量,它们可能使用assert(3) -并间接调用了abort )。 I guess that in caffe the various CHECK* macros could indirectly call abort . 我猜想在caffe中 ,各种CHECK*宏都可以间接调用abort I leave you to investigate that. 我让你去调查。

If you don't have the source code or don't have the capacity or time to fix that bug in that third party library, you should give up using that library and use something else. 如果您没有源代码,或者没有能力或时间修复该第三方库中的错误,则应放弃使用该库,而使用其他方法。

In many cases, you should trust external libraries more than your own code. 在许多情况下,您应该比自己的代码更信任外部库。 Probably, you are abusing or misusing that library. 可能是您滥用或滥用该库。 Read carefully its documentation and be sure that your own code calling it is using that library correctly and respects its invariants and conventions. 仔细阅读其文档,并确保调用它的自己的代码正确使用了该库,并尊重其不变式和约定。 Probably the bug is in your own code , at some other place. 该错误可能在其他地方的您自己的代码中

I want to keep running my program 我想继续运行我的程序

This is impossible (or very unreliable, so unreasonable). 这是不可能的(或者非常不可靠,所以不合理)。 I guess that your program has some undefined behavior . 我猜您的程序有一些未定义的行为 Be very scared , and work hard to avoid UB. 非常 害怕 ,并努力避免UB。

You need to improve your debugging skills. 您需要提高调试技能。 Learn better how to use the gdb debugger , valgrind , GCC sanitizers (eg instrumentation options like -fsanitize=address , -fsanitize=undefined and others), etc... 更好地了解如何使用gdb调试器valgrind ,GCC消毒器(例如-fsanitize=address-fsanitize=undefined检测工具选项 )等。

You reasonably should not try to handle SIGABRT even if in principle you might (but then read carefully signal(7) , signal-safety(7) and hints about handling Unix signals in Qt ). 即使原则上您可以合理地尝试处理SIGABRT (但请仔细阅读signal(7)signal-safety(7)以及有关在Qt中处理Unix信号的提示)。 I strongly recommend to avoid even trying catching SIGABRT . 我强烈建议您避免尝试捕获SIGABRT

Unfortunately, you can't . 不幸的是,你不能 SIGABRT signal is itself sent right after abort() SIGABRT信号本身在abort()之后立即发送

Ref: https://stackoverflow.com/a/3413215/9332965 参考: https : //stackoverflow.com/a/3413215/9332965

You can handle SIGABRT , but you probably shouldn't . 可以处理SIGABRT ,但您可能不应该这样做


The "can" is straightforward - just trap it in the usual way, using signal() . “罐头”很简单-使用signal()以通常的方式捕获它。 You don't want to return from this signal handler - you probably got here from abort() - possibly originally from assert() - and that function will exit after raising the signal. 您不想从该信号处理程序中返回-您可能是从abort()到达这里的-可能最初是从assert()到达的-并且该函数将在引发信号后退出。 You could however longjmp() back to a state you set up earlier. 但是,您可以将longjmp()恢复为之前设置的状态。


The "shouldn't" is because once SIGABRT has been raised, your data structures (including those of Qt and any other libraries) are likely in an inconsistent state and actually using any of your program's state is likely to be unpredictable at best. “不应该”是因为一旦引发了SIGABRT ,您的数据结构(包括Qt和任何其他库的数据结构)可能处于不一致状态,而实际上使用程序的任何状态充其量都是不可预测的。 Apart from exiting immediately, there's not much you can do other than exec() a replacement program to take over in a sane initial state. 除了立即退出之外,除了exec()替换程序可以在健全的初始状态下接管之外,您无能为力。

If you just want to show a friendly message, then you perhaps could exec() a small program to do that (or just use xmessage ), but beware of exiting this with a success status where you would have had an indication of the SIGABRT otherwise. 如果您只想显示一条友好的消息,则可以exec()一个小程序来执行此操作(或仅使用xmessage ),但是请注意,不要以成功状态退出该状态,否则将显示SIGABRT

Unfortunately there isn't much you can do to prevent SIGABRT from terminating your program. 不幸的是,您没有什么可以阻止SIGABRT终止程序的。 Not without modifying some code that was hopefully written by you. 并非没有修改您希望编写的某些代码。

You would either need to change code to not throw an abort, or you would have to spawn a new process that runs the code instead of the current process. 您可能需要更改代码以不中止操作,或者必须生成一个运行该代码的新进程而不是当前进程。 I do not suggest you use a child process to solve this problem. 我不建议您使用子进程来解决此问题。 It's most likely caused by misuse of an api or computer resources, such as low memory. 这很可能是由于滥用api或计算机资源(例如内存不足)引起的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM