去信号处理

我对 Go 很陌生,并且一直在试图弄清楚如何处理需要返回主循环的事件。


在 C 中,我可以只返回函数,但似乎我不能在这里这样做,至少用那个方法是这样。


我可以处理需要在 sigHandler() 中处理的信号,即 SIGINT 或 SIGTERM 但我需要在处理 SIGHUP 或 SIGUSR 时将调用返回到 main。在我下面的代码中,一旦我发送挂断信号,进程就会陷入等待模式。


如果有人可以帮助我指导我如何正确设计信号处理以处理需要返回到第一个 goroutine 中的主代码的调用,我将不胜感激。


编辑

我现在在 select{} 中的主 goroutine 中处理通道消息,但是当我发送 HUP 信号时,下面的代码退出。这里的目标是重新加载配置并继续正常执行。


在主线代码中,我有这个:


go sigHandler()

cs := make(chan bool, 1)

go sigHandler(cs)


// setup the http server

err := setupServer(addr, port)

if err != nil {

    fatal("Error setting up listening sockets")

    os.Exit(1)

}


    select {

    case quit := <-cs:

        if quit {

            logEvent(loginfo, sys, "Terminating..")

            closeLog()

            os.Exit(0)

        } else {

            logEvent(loginfo, sys, "Reloading configuration..")

            }

    }

函数 sigHandler()


func sigHandler(cs chan bool) {

    c := make(chan os.Signal, 1)

    signal.Notify(c, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)


    signal := <-c

    logEvent(lognotice, sys, "Signal received: "+signal.String())


    switch signal {

    case syscall.SIGINT, syscall.SIGTERM:

        cs <- true

    case syscall.SIGHUP:

            cs <- false

    }

}


慕的地8271018
浏览 162回答 2
2回答

噜噜哒

你可以这样做:package mainimport (&nbsp; &nbsp; &nbsp; &nbsp; "os"&nbsp; &nbsp; &nbsp; &nbsp; "os/signal"&nbsp; &nbsp; &nbsp; &nbsp; "syscall")// We make sigHandler receive a channel on which we will report the value of var quitfunc sigHandler(q chan bool) {&nbsp; &nbsp; &nbsp; &nbsp; var quit bool&nbsp; &nbsp; &nbsp; &nbsp; c := make(chan os.Signal, 1)&nbsp; &nbsp; &nbsp; &nbsp; signal.Notify(c, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)&nbsp; &nbsp; &nbsp; &nbsp; // foreach signal received&nbsp; &nbsp; &nbsp; &nbsp; for signal := range c {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //&nbsp; &nbsp; &nbsp; logEvent(lognotice, sys, "Signal received: "+signal.String())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; switch signal {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case syscall.SIGINT, syscall.SIGTERM:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; quit = true&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case syscall.SIGHUP:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; quit = false&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if quit {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; quit = false&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; closeDb()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; logEvent(loginfo, sys, "Terminating..")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; closeLog()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; os.Exit(0)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // report the value of quit via the channel&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; q <- quit&nbsp; &nbsp; &nbsp; &nbsp; }}func main() {&nbsp; &nbsp; &nbsp; &nbsp; // init two channels, one for the signals, one for the main loop&nbsp; &nbsp; &nbsp; &nbsp; sig := make(chan bool)&nbsp; &nbsp; &nbsp; &nbsp; loop := make(chan error)&nbsp; &nbsp; &nbsp; &nbsp; // start the signal monitoring routine&nbsp; &nbsp; &nbsp; &nbsp; go sigHandler(sig)&nbsp; &nbsp; &nbsp; &nbsp; // while vat quit is false, we keep going&nbsp; &nbsp; &nbsp; &nbsp; for quit := false; !quit; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // we start the main loop code in a goroutine&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Main loop code here&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // we can report the error via the chan (here, nil)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; loop <- nil&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // We block until either a signal is received or the main code finished&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; select {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // if signal, we affect quit and continue with the loop&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case quit = <-sig:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // if no signal, we simply continue with the loop&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; case <-loop:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }}但是请注意,该信号会导致主循环继续,但不会停止在第一个 goroutine 上的执行。

慕雪6442864

这是一种结构化事物来做你想做的事情的方法,分离关注点,这样信号处理代码和主代码是分开的,并且很容易独立测试。如何实现 Quit 和 ReloadConfig 完全取决于您的程序 - ReloadConfig 可能会在通道上向正在运行的 goroutine 发送“请重新加载”值;它可能会锁定互斥锁并更改一些共享配置数据;或其他一些可能性。package mainimport (&nbsp; &nbsp; "log"&nbsp; &nbsp; "os"&nbsp; &nbsp; "os/signal"&nbsp; &nbsp; "syscall")func main() {&nbsp; &nbsp; obj := &myObject{}&nbsp; &nbsp; go handleSignals(obj)&nbsp; &nbsp; select {}}type myObject struct {}func (obj *myObject) Quit() {&nbsp; &nbsp; log.Printf("quitting")&nbsp; &nbsp; os.Exit(0)}func (obj *myObject) ReloadConfig() {&nbsp; &nbsp; log.Printf("reloading configuration")}type MainObject interface {&nbsp; &nbsp; ReloadConfig()&nbsp; &nbsp; Quit()}func handleSignals(main MainObject) {&nbsp; &nbsp; c := make(chan os.Signal, 1)&nbsp; &nbsp; signal.Notify(c, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)&nbsp; &nbsp; for sig := range c {&nbsp; &nbsp; &nbsp; &nbsp; switch sig {&nbsp; &nbsp; &nbsp; &nbsp; case syscall.SIGINT, syscall.SIGTERM:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; main.Quit()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; &nbsp; &nbsp; case syscall.SIGHUP:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; main.ReloadConfig()&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go