CGO: 处理 SIGTERM / SIGABRT 信号

huangapple go评论87阅读模式
英文:

CGO: handle SIGTERM / SIGABRT

问题

我正在调用一个使用 asserta 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 &lt;signal.h&gt;
// #define MPE_Assert(_Expression) (void) ((!!(_Expression)) || (raise(SIGTERM)))
import &quot;C&quot;
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 &lt;- poly2Tri(verts, holes)
	}()

	select {
	case res := &lt;-result:
		return res
	case &lt;-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调用设置)来处理SIGTERMSIGABRT信号。

然而,SIGTERMSIGABRT处理程序不应该阻止进程终止。它可以进行一些尽力而为的日志记录(可能有助于调试),或者刷新中间输出(以减少丢失的工作量),但通常情况下,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.

huangapple
  • 本文由 发表于 2021年7月15日 02:54:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/68383705.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定