lib/http: shutdown all servers on exit to remove unix socket

Before this change only serve http was Shutting down its server which
was causing other servers such as serve restic to leave behind their
unix sockets.

This change moves the finalisation to lib/http so all servers have it
and removes it from serve http.

Fixes #6648
This commit is contained in:
Nick Craig-Wood 2022-12-22 16:52:43 +00:00
parent b1b62f70d3
commit 638058ef91
2 changed files with 15 additions and 15 deletions

View File

@ -11,14 +11,12 @@ import (
"path" "path"
"strconv" "strconv"
"strings" "strings"
"sync"
"time" "time"
"github.com/go-chi/chi/v5/middleware" "github.com/go-chi/chi/v5/middleware"
"github.com/rclone/rclone/cmd" "github.com/rclone/rclone/cmd"
"github.com/rclone/rclone/fs" "github.com/rclone/rclone/fs"
"github.com/rclone/rclone/fs/accounting" "github.com/rclone/rclone/fs/accounting"
"github.com/rclone/rclone/lib/atexit"
libhttp "github.com/rclone/rclone/lib/http" libhttp "github.com/rclone/rclone/lib/http"
"github.com/rclone/rclone/lib/http/serve" "github.com/rclone/rclone/lib/http/serve"
"github.com/rclone/rclone/vfs" "github.com/rclone/rclone/vfs"
@ -82,17 +80,6 @@ control the stats printing.
log.Fatal(err) log.Fatal(err)
} }
var finaliseOnce sync.Once
finalise := func() {
finaliseOnce.Do(func() {
if err := s.server.Shutdown(); err != nil {
log.Printf("error shutting down server: %v", err)
}
})
}
fnHandle := atexit.Register(finalise)
defer atexit.Unregister(fnHandle)
s.server.Wait() s.server.Wait()
return nil return nil
}) })

View File

@ -19,6 +19,7 @@ import (
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
"github.com/rclone/rclone/fs/config/flags" "github.com/rclone/rclone/fs/config/flags"
"github.com/rclone/rclone/lib/atexit"
"github.com/spf13/pflag" "github.com/spf13/pflag"
) )
@ -145,6 +146,7 @@ type Server struct {
template *TemplateConfig template *TemplateConfig
htmlTemplate *template.Template htmlTemplate *template.Template
usingAuth bool // set if we are using auth middleware usingAuth bool // set if we are using auth middleware
atexitHandle atexit.FnHandle
} }
// Option allows customizing the server // Option allows customizing the server
@ -390,6 +392,8 @@ func (s *Server) Serve() {
// log.Printf("listening on %s", ii.url) // log.Printf("listening on %s", ii.url)
go ii.serve(&s.wg) go ii.serve(&s.wg)
} }
// Install an atexit handler to shutdown gracefully
s.atexitHandle = atexit.Register(func() { _ = s.Shutdown() })
} }
// Wait blocks while the server is serving requests // Wait blocks while the server is serving requests
@ -402,14 +406,23 @@ func (s *Server) Router() chi.Router {
return s.mux return s.mux
} }
// Time to wait to Shutdown an HTTP server
const gracefulShutdownTime = 10 * time.Second
// Shutdown gracefully shuts down the server // Shutdown gracefully shuts down the server
func (s *Server) Shutdown() error { func (s *Server) Shutdown() error {
ctx := context.Background() // Stop the atexit handler
if s.atexitHandle != nil {
atexit.Unregister(s.atexitHandle)
s.atexitHandle = nil
}
for _, ii := range s.instances { for _, ii := range s.instances {
expiry := time.Now().Add(gracefulShutdownTime)
ctx, cancel := context.WithDeadline(context.Background(), expiry)
if err := ii.httpServer.Shutdown(ctx); err != nil { if err := ii.httpServer.Shutdown(ctx); err != nil {
log.Printf("error shutting down server: %s", err) log.Printf("error shutting down server: %s", err)
continue
} }
cancel()
} }
s.wg.Wait() s.wg.Wait()
return nil return nil