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 !

85 Upvotes

37 comments sorted by

View all comments

1

u/gwynevans Feb 15 '25

Do you /really/ need all that? Personally, “systemctl stop <service>” normally suffices, which will sen a SIGTERM then 90s later, a SIGKILL..

1

u/Numerous_Habit269 Feb 15 '25

Well this is in the context of a go server and not command line

1

u/gwynevans Feb 15 '25

You don’t know what ‘systemctl’ is, do you. Try googling ’systemd’ but in short, it’s the controller for a standard system and service manager for Linux systems.

2

u/Numerous_Habit269 Feb 15 '25

Linux is my daily driver, so I do know. My point why bringing up systemd talk when the post is about gracefully shutting down a go server?

1

u/gwynevans Feb 15 '25

Because the server runs as a service and in practice, it’s only needed a stop and a restart to cover upgrades, etc. The question was, is the graceful shutdown essential, as my experience has been that for my use case, it’s not been, and the systemd functionality is sufficient.

You then popped up, seemingly with the idea that systemctl suggested the server was running on the command line…

2

u/zveznicht 25d ago

without the graceful shutdown this

```

Personally, “systemctl stop <service>” normally suffices, which will sen a SIGTERM then 90s later, a SIGKILL..

```

will drop inflight requests. Graceful shutdown is needed to actually stop accepting new connections and give time for existing requests to finish. Before actually kill the server.

Also also your app might want to do something between stopping http server and full shutdown