1
0
mirror of https://github.com/rclone/rclone.git synced 2025-12-15 15:53:41 +00:00

vfs: fix SIGHUP killing serve instead of flushing directory caches

Before, rclone serve would crash when sent a SIGHUP which contradicts
the documentation - saying it should flush the directory caches.

Moved signal handling from the mount into the vfs layer, which now
handles SIGHUP on all uses of the VFS including mount and serve.

Fixes #8607
This commit is contained in:
dougal
2025-09-01 12:14:57 +01:00
committed by Nick Craig-Wood
parent 9e200531b1
commit a4962e21d1
5 changed files with 34 additions and 25 deletions

14
vfs/sighup.go Normal file
View File

@@ -0,0 +1,14 @@
//go:build !plan9 && !js
package vfs
import (
"os"
"os/signal"
"syscall"
)
// NotifyOnSigHup makes SIGHUP notify given channel on supported systems
func NotifyOnSigHup(sighupChan chan os.Signal) {
signal.Notify(sighupChan, syscall.SIGHUP)
}

10
vfs/sighup_unsupported.go Normal file
View File

@@ -0,0 +1,10 @@
//go:build plan9 || js
package vfs
import (
"os"
)
// NotifyOnSigHup makes SIGHUP notify given channel on supported systems
func NotifyOnSigHup(sighupChan chan os.Signal) {}

View File

@@ -179,6 +179,7 @@ type VFS struct {
root *Dir
Opt vfscommon.Options
cache *vfscache.Cache
cancel context.CancelFunc
cancelCache context.CancelFunc
usageMu sync.Mutex
usageTime time.Time
@@ -197,8 +198,10 @@ var (
// DefaultOpt will be used
func New(f fs.Fs, opt *vfscommon.Options) *VFS {
fsDir := fs.NewDir("", time.Now())
ctx, cancel := context.WithCancel(context.Background())
vfs := &VFS{
f: f,
f: f,
cancel: cancel,
}
vfs.inUse.Store(1)
@@ -259,6 +262,9 @@ func New(f fs.Fs, opt *vfscommon.Options) *VFS {
go vfs.refresh()
}
// Handle supported signals
go vfs.signalHandler(ctx)
// This can take some time so do it after the Pin
vfs.SetCacheMode(vfs.Opt.CacheMode)
@@ -274,6 +280,27 @@ func (vfs *VFS) refresh() {
}
}
// Reload VFS cache on SIGHUP
func (vfs *VFS) signalHandler(ctx context.Context) {
sigHup := make(chan os.Signal, 1)
NotifyOnSigHup(sigHup)
waiting := true
for waiting {
select {
case <-ctx.Done():
waiting = false
case <-sigHup:
root, err := vfs.Root()
if err != nil {
fs.Errorf(vfs.Fs(), "Error reading root: %v", err)
} else {
root.ForgetAll()
}
}
}
}
// Stats returns info about the VFS
func (vfs *VFS) Stats() (out rc.Params) {
out = make(rc.Params)
@@ -372,6 +399,9 @@ func (vfs *VFS) Shutdown() {
close(vfs.pollChan)
vfs.pollChan = nil
}
// Cancel any background go routines
vfs.cancel()
}
// CleanUp deletes the contents of the on disk cache