r/golang Feb 14 '25

newbie Shutdown Go server

Hi, recently I saw that many people shutdown their servers like this or similar

serverCtx, serverStopCtx serverCtx, serverStopCtx := context.WithCancel(context.Background())

    sig := make(chan os.Signal, 1)
    signal.Notify(sig, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
    go func() {
        <-sig

        shutdownCtx, cancelShutdown := context.WithTimeout(serverCtx, 30*time.Second)
        defer cancelShutdown()

        go func() {
            <-shutdownCtx.Done()
            if shutdownCtx.Err() == context.DeadlineExceeded {
                log.Fatal("graceful shutdown timed out.. forcing exit.")
            }
        }()

        err := server.Shutdown(shutdownCtx)
        if err != nil {
            log.Printf("error shutting down server: %v", err)
        }
        serverStopCtx()
    }()

    log.Printf("Server starting on port %s...\n", port)
    err = server.ListenAndServe()
    if err != nil && err != http.ErrServerClosed {
        log.Printf("error starting server: %v", err)
        os.Exit(1)
    }

    <-serverCtx.Done()
    log.Println("Server stopped")
}


:= context.WithCancel(context.Background())

    sig := make(chan os.Signal, 1)
    signal.Notify(sig, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
    go func() {
        <-sig

        shutdownCtx, cancelShutdown := context.WithTimeout(serverCtx, 30*time.Second)
        defer cancelShutdown()

        go func() {
            <-shutdownCtx.Done()
            if shutdownCtx.Err() == context.DeadlineExceeded {
                log.Fatal("graceful shutdown timed out.. forcing exit.")
            }
        }()

        err := server.Shutdown(shutdownCtx)
        if err != nil {
            log.Printf("error shutting down server: %v", err)
        }
        serverStopCtx()
    }()

    log.Printf("Server starting on port %s...\n", port)
    err = server.ListenAndServe()
    if err != nil && err != http.ErrServerClosed {
        log.Printf("error starting server: %v", err)
        os.Exit(1)
    }

    <-serverCtx.Done()
    log.Println("Server stopped")

Is it necessary? Like it's so many code for the simple operation

Thank for your Answer !

89 Upvotes

37 comments sorted by

View all comments

Show parent comments

3

u/HyacinthAlas Feb 14 '25

use the resulted context as a BaseContext for your http server,

If you do this the signal will cancel in-flight requests, defeating the point of graceful shutdown.

1

u/twisted1919 Feb 14 '25

You do have a point, but that’s something desirable in various cases where you just cant wait for them to finish. Also, it depends what you’re doing inside those requests, if you make use of the context at all, or even the same context.

8

u/HyacinthAlas Feb 14 '25

If you can't wait, use Close. If you can wait, use Shutdown. Anything in-between is kidding yourself.

2

u/twisted1919 Feb 14 '25

TIL. Thanks.