CGO:交易 SIGTERM / SIGABRT

CGO: handle SIGTERM / SIGABRT

我在很多地方打电话给a c library that uses assert。这对我来说是个问题,因为我不希望我的应用程序在断言失败时终止。

设置 NDEBUG 标志以禁用断言没有帮助,因为它只会导致段错误。

这是我目前得到的结果,但未捕获到 SIGTERM。

// 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{}
    }
}

那么,如何在断言失败时允许库退出但允许我的应用程序继续?

我认为 poly2Tri 函数与此问题无关,但如果需要我可以添加它。

可以在 C 中使用 signal.Notify in native Go code or sigaction 处理 SIGTERMSIGABRT(可能通过 cgo 调用设置)。

但是,SIGTERMSIGABRT 处理程序应该 而不是 阻止进程终止 — 它可以做一些尽力而为的日志记录(也许是为了帮助在调试中),或刷新中间输出(以减少丢失的工作量),但通常 assert 失败可能表明程序在某种程度上严重损坏 — 如果它继续 运行,它可能会产生任意错误的输出(例如由于内存损坏),或段错误(因为程序不希望调用 assert 到 return),或死锁(因为 assert 表明一个损坏的锁定不变量)。

如果您在处理 运行 导致 assert 故障的程序时遇到问题,与其试图捕获和抑制这些故障,不如寻找重现它们的方法(例如通过 fuzzing 您程序的输入,或记录失败前程序正在执行的操作)。然后您可以修复 assert 故障的根本原因,并且您无需尝试从中恢复。