HTTP.Server关闭导致运行时错误

时间:2017-11-20 14:33:36

标签: go goroutine panic

我在darwin / amd64上的Go 1.9.2中编写了一个goroutine,它导致运行时错误:无效的内存地址或无指针取消引用。我认为这是因为某种类型的竞赛条件与例行程序有关,但我不确定。

主应用程序正在做一些事情,所以我将web服务器作为goroutine启动,然后侦听来自父进程的退出信号,并尝试在返回之前将所有内容干净地关闭。

这里的功能是:

// WebServer defines the handler endpoints and launches the web server listener
func WebServer(wg *sync.WaitGroup) {

    // Make sure the exit is noted
    defer wg.Done()

    // Endpoint, handler function
    http.HandleFunc("/version", WebShowVersion)

    // Go forth and serve
    // Define the server struct
    srv := &http.Server{Addr: ":8080"}

    // Now go serve
    chnToLogger <- "Launching web server on port 8080"
    go func() {
        err := srv.ListenAndServe()
        if err != nil &&
            err.Error() != "http: Server closed" {

            // There...was an error
            chnToLoggerError <- "Error launching web server: " + err.Error()
        }
    }()

    // Listen for a shutdown
    for {
        select {
        case <-chnQuitNow:

            // Shut down the process
            chnToLogger <- "Shutting down web server process"
            if err := srv.Shutdown(nil); err != nil {

                // There was a problem shutting down gracefully
                chnToLoggerError <- "Error shutting down web server: " + err.Error()
                return
            }

            // Done
            chnToLogger <- "Web server has shut down now"
            return

        default:
            continue
        }
    }

    // Done
    return
}

恐慌状态:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x28 pc=0x11f7e61]

goroutine 10 [running]:
net/http.(*Server).Shutdown(0xc420158000, 0x0, 0x0, 0x0, 0x0)
    /usr/local/go/src/net/http/server.go:2506 +0x1b1
main.WebServer(0xc4200164a0)
    /Users/me/go/src/testproj/webhandling.go:45 +0x146
created by main.main
    /Users/me/go/src/testproj/main.go:94 +0x3d6

webhandling.go中的第45行是:

if err := srv.Shutdown(nil); err != nil {

虽然它在被触发时不一致,但似乎只有在我启动程序并使用Web客户端拉动localhost:8080 /版本几次时才会出现这种情况,这让我想知道是否srv.Shutdown (nil)试图关闭一个有引用但已经退出的连接?

1)是否可以让服务器在从goroutine返回之前安全完整地关闭Web服务器进程?

2)导致不一致的运行时错误被触发的原因是什么?

1 个答案:

答案 0 :(得分:4)

绝不使用nil上下文。使用context.Background()context.TODO()