mount: remove the local control socket when the mount exits (#12560)

* mount: remove the local control socket when the mount exits

weed mount listened on /tmp/seaweedfs-mount-<hash>.sock and removed it only
when a later mount of the same directory started, so every unmount or
SIGTERM left one socket file behind. Remove it on the normal return path and
in the interrupt hook, unless a later mount of the same directory has
already replaced it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* mount: remove the control socket before a failed mount exits

glog.Fatalf and glog.Exitf call os.Exit, which skips the deferred removal,
so a mount that failed after creating its socket (mount point not
available, fusermount failure) still left it behind.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* mount: register the socket cleanup hook before mount setup

A SIGTERM that arrived while the mount was still setting up, for example
waiting on the filer to create the mount root, exited through grace without
running the deferred cleanup. Registering the hook right after the listener
is created makes it run last, after the unmount and filesystem hooks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Chris LuandClaude Opus 5.5 authored and GitHub committed 2026-11-11 10:11:58 -08:00
1 parent 7f18576798
commit b11af30cb1
4 files changed
+73

No files matched your search

+22
View File
@@ -14,6 +14,7 @@ import (
"runtime/debug"
"strconv"
"strings"
"sync"
"time"
"google.golang.org/grpc"
@@ -269,6 +270,27 @@ func createMountRoot(wfs *mount.WFS, mountRoot, bucketRootPath string, filerAddr
return true
}
// mountSocketCleanup returns a func that removes the control socket this mount
// listens on, unless a later mount of the same directory has replaced it.
func mountSocketCleanup(socketPath string) func() {
listened, err := os.Lstat(socketPath)
if err != nil {
return func() {}
}
var once sync.Once
return func() {
once.Do(func() {
current, err := os.Lstat(socketPath)
if err != nil || !os.SameFile(current, listened) {
return
}
if err := os.Remove(socketPath); err != nil && !os.IsNotExist(err) {
glog.Warningf("remove mount socket %s: %v", socketPath, err)
}
})
}
}
// serveMountGrpc exposes the local control socket used by "weed mount.stats".
func serveMountGrpc(wfs *mount.WFS, listener net.Listener) {
grpcS := pb.NewGrpcServer()