英文:
CGO: handle SIGTERM / SIGABRT
问题
我正在调用一个使用 assert 的 a C 库。对我来说,这是一个问题,因为我不希望应用程序在断言失败时终止。
将 NDEBUG
标志设置为禁用断言并不能解决问题,因为它只会导致段错误。
以下是我目前的代码,但是 SIGTERM 无法捕获。
// 重新定义 MPE_Assert 宏以使用 SIGTERM,因为 SIGABRT 无法停止。
// #include <signal.h>
// #define MPE_Assert(_Expression) (void) ((!!(_Expression)) || (raise(SIGTERM)))
import "C"
func Poly2Tri(verts [][2]float32, holes [][][2]float32) [][2]float32 {
sig := make(chan os.Signal, 10)
result := make(chan [][2]float32)
defer signal.Stop(sig)
go func() {
// 通知所有信号
signal.Notify(sig)
result <- poly2Tri(verts, holes)
}()
select {
case res := <-result:
return res
case <-sig:
return [][2]float32{}
}
}
那么,我该如何让库在断言失败时退出,但允许我的应用程序继续运行呢?
我认为 poly2Tri
函数与此问题无关,但如果需要,我可以添加它。
英文:
I am calling a c library that uses assert in many places. This is a problem for me because I don't want my application to terminate when an assert fails.
Setting the NDEBUG
flag to disable the asserts doesn't help as it just leads to a segfault.
Here is what I've got so far but the SIGTERM is not caught.
// Redefine the MPE_Assert macro to use SIGTERM since SIGABRT cannot be stopped.
// #include <signal.h>
// #define MPE_Assert(_Expression) (void) ((!!(_Expression)) || (raise(SIGTERM)))
import "C"
func Poly2Tri(verts [][2]float32, holes [][][2]float32) [][2]float32 {
sig := make(chan os.Signal, 10)
result := make(chan [][2]float32)
defer signal.Stop(sig)
go func() {
// Notify for all signals
signal.Notify(sig)
result <- poly2Tri(verts, holes)
}()
select {
case res := <-result:
return res
case <-sig:
return [][2]float32{}
}
}
So, how do I allow the library to exit when an assert fails but allow my application to continue?
I'dont think that the poly2Tri
function is relevant for this issue but I can add it if needed.
答案1
得分: 1
可以使用Go语言中的signal.Notify
或C语言中的sigaction
(通过cgo调用设置)来处理SIGTERM
和SIGABRT
信号。
然而,SIGTERM
或SIGABRT
处理程序不应该阻止进程终止。它可以进行一些尽力而为的日志记录(可能有助于调试),或者刷新中间输出(以减少丢失的工作量),但通常情况下,assert
失败可能表明程序在某种程度上出现了严重错误。如果程序继续运行,可能会产生任意错误的输出(例如由于内存损坏),或者由于程序不希望assert
调用返回而导致段错误,或者由于assert
指示了破坏的锁定不变式而导致死锁。
如果你的程序遇到assert
失败的问题,与其尝试捕获和抑制这些失败,更有成效的做法是寻找重现它们的方法(例如通过模糊测试程序的输入,或在失败之前记录程序的跟踪)。然后,你可以修复assert
失败的根本原因,这样就不需要尝试从中恢复。
英文:
It is possible to handle SIGTERM
and SIGABRT
using signal.Notify
in native Go code or sigaction
in C (perhaps set up via a cgo call).
However, a SIGTERM
or SIGABRT
handler should not stop the process from terminating — it can do some best-effort logging (perhaps to aid in debugging), or flush intermediate output (to reduce the amount of work lost), but in general an assert
failure may indicate that the program is badly broken in some way — if it continues to run, it may produce arbitrarily wrong output (e.g. due to memory corruption), or segfault (because the program does not expect the call to assert
to return), or deadlock (because the assert
indicates a broken locking invariant).
If you are having trouble with a program running into assert
failures, rather than trying to trap and suppress those failures, it may be more productive to look for ways to reproduce them (such as by fuzzing your program's inputs, or logging a trace of what the program is doing before the failure). Then you can fix the underlying cause of the assert
failures, and you won't need to try to recover from them.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论