审核有关忽略上下文取消功能的警告

时间:2019-07-23 02:07:56

标签: go

我正在将超时上下文传递给Server.Shutdown(http包)。我看不到我需要调用返回的cancel函数,所以我忽略了它。但是当我跑步时,兽医说the cancel function returned by context.WithTimeout should be called, not discarded, to avoid a context leak

如果没有问题,我该如何解决该问题或避免出现go vet错误消息?

    go signalShutdown(server, stopCh)

    if err := server.ListenAndServeTLS(cert, key); err != http.ErrServerClosed {
        log.Fatalf("ListenAndServeTLS() error: %v\n", err)
    }
    // Note: exit here does not terminate main()
}

// signalShutdown waits for a notification from the OS that the http server
// should be shutdown, then gracefully stops it.
func signalShutdown(server *http.Server, stopCh <-chan struct{}) {
    const ForceShutdownAfter = 10 // Shutdown context times out after this many seconds

    // Setup chan to receive notification of when server should shut down
    quitCh := make(chan os.Signal, 1)
    signal.Notify(quitCh, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)

    // Wait until we get a notification to stop the server
    select {
    case <-quitCh:
        log.Println("WEB : OS signal received on", server.Addr)
    case <-stopCh:
        log.Println("WEB : Shutdown message received on", server.Addr)
    }

    context, _ := context.WithTimeout(context.Background(), ForceShutdownAfter*time.Second)

    // Tell the server to shutdown but only after blocking new connections and waiting for the
    // existing connections to finish (OR if context expires - see ForceShutdownAfter above)
    if err := server.Shutdown(context); err != nil {
        log.Fatalf("Shutdown() error: %v", err)
    }

    os.Exit(0)
}

2 个答案:

答案 0 :(得分:2)

  

... the cancel function returned by context.WithTimeout should be called, not discarded, to avoid a context leak

     

如果没有问题,我该如何解决该问题或避免出现go vet错误消息?

通过调用,而不丢弃as documented函数,this link

cancel

答案 1 :(得分:-1)

创建上下文对象的方法很少,其中一种是使用context.WithTimeout()

通过使用带超时的上下文,我们可以放置一些处理程序,该处理程序将在使用上下文的过程超出定义的超时时触发。看看下面基于您的代码的示例:

context, cancel := context.WithTimeout(context.Background(), ForceShutdownAfter*time.Second)
defer cancel()

chanErr := make(chan error, 1)

go func () {
    chanErr <- server.Shutdown(context)
}()

select {
case <-context.Done():
    log.Fatalf("Shutdown() timeout")
case chanErr := <-chanErr:
    log.Fatalf("Shutdown() error: %v", errMessage)
}

os.Exit(0)

在上面的代码中,我们可以看到context.WithTimeout()返回两个变量,第二个变量是cancel,它是一个函数,需要使用defer关键字进行调用。此外,关闭错误和上下文超时都应谨慎处理。这些是实现上下文超时处理程序的示例。

您的示例中出现警告,因为cancel被忽略。

更多信息:https://blog.golang.org/context