微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 golang 中处理 SIGINT (ctrl-c) 以将其转换为恐慌

如何解决在 golang 中处理 SIGINT (ctrl-c) 以将其转换为恐慌

我的目标是为 SIGINT(即 CLI 上的 Ctrl-C)提供一个处理程序,它允许运行延迟的函数调用而不是导致硬退出。这个用例是在一个测试套件中运行很长时间的测试,我希望 CLI 用户能够在需要时使用 Ctrl-C 尽早触发测试清理。测试清理函数应该都在每个测试函数的延迟函数堆栈上,所以在我看来,将 SIGINT 降级为恐慌应该会导致这些清理函数运行。

下面的代码是我尝试这样做的。如果你用 go run . 运行它,你会看到

$ go run .
regular action ran!
post-Sleep action ran!
deferred action ran!

但是如果你在 5 秒的睡眠期间打断它,你会看到这个:

regular action ran!^Cpanic: interrupt

goroutine 8 [running]:
main.panic_on_interrupt(0xc00007c180)
        /home/curran/dev/test/main.go:12 +0x5e
created by main.main
        /home/curran/dev/test/main.go:20 +0xab
exit status 2

添加了中断处理程序和 goroutine,因为我认为这会将 SIGINT 降级为恐慌并允许对 fmt.Printf("deferred action ran!")调用执行。然而,事实并非如此。

这是有问题的代码

package main

import (
        "fmt"
        "time"
        "os"
        "os/signal"
)

func panic_on_interrupt(c chan os.Signal) {
        sig := <-c
        panic(sig)
}

func main() {
        c := make(chan os.Signal,1)
        // Passing no signals to Notify means that
        // all signals will be sent to the channel.
        signal.Notify(c,os.Interrupt)
        go panic_on_interrupt(c)

        fmt.Printf("regular action ran!")
        defer fmt.Printf("deferred action ran!")
        time.Sleep(5 * time.Second)
        fmt.Printf("post-Sleep action ran!")
}                                                                                                                                                                                                                                             

解决方法

__init_subclass__

initContainers: - name: take-data-dir-ownership image: alpine:3 # Give `mysql` user permissions a mounted volume # https://stackoverflow.com/a/51195446/4360433 command: - chown - -R - 999:999 - /var/lib/mysql volumeMounts: - name: data mountPath: /var/lib/mysql 阻止在指定时间内运行 goroutine。
您可以func main() { fmt.Printf("regular action ran!") defer fmt.Printf("deferred action ran!") go startLongRunningTest() defer longRunningTestCleanupCode() //time.Sleep(5 * time.Second) //fmt.Printf("post-Sleep action ran!") c := make(chan os.Signal,1) signal.Notify(c,os.Interrupt) <-c } 清理代码。
此外,您可以在单独的 goroutine 中运行耗时的测试,而不是在那里恐慌。
尽可能避免使用 time.Sleep()

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。