1
0
mirror of https://github.com/rclone/rclone.git synced 2026-01-05 18:13:17 +00:00

mount: notice daemon dying much quicker

Before this change we waited until until the timeout to check the
daemon was alive.

Now we check it every 100ms like we do the mount status.

This also fixes compiling on all platforms which was broken by the
previous change

9bfbf2a4a mount: fix macOS not noticing errors with --daemon

See: https://forum.rclone.org/t/rclone-mount-daemon-exits-successfully-even-when-mount-fails/43146
This commit is contained in:
Nick Craig-Wood
2023-11-29 15:11:11 +00:00
parent 97d7945cef
commit caf5dd9d5e
5 changed files with 66 additions and 45 deletions

View File

@@ -7,15 +7,10 @@ import (
"fmt"
"path/filepath"
"strings"
"time"
"github.com/moby/sys/mountinfo"
)
const (
pollInterval = 100 * time.Millisecond
)
// CheckMountEmpty checks if folder is not already a mountpoint.
// On Linux we use the OS-specific /proc/self/mountinfo API so the check won't access the path.
// Directories marked as "mounted" by autofs are considered not mounted.
@@ -80,19 +75,5 @@ func CheckMountReady(mountpoint string) error {
return fmt.Errorf(msg, mountpointAbs)
}
// WaitMountReady waits until mountpoint is mounted by rclone.
func WaitMountReady(mountpoint string, timeout time.Duration) (err error) {
endTime := time.Now().Add(timeout)
for {
err = CheckMountReady(mountpoint)
delay := time.Until(endTime)
if err == nil || delay <= 0 {
break
}
if delay > pollInterval {
delay = pollInterval
}
time.Sleep(delay)
}
return
}
// CanCheckMountReady is set if CheckMountReady is functional
var CanCheckMountReady = true

View File

@@ -3,10 +3,6 @@
package mountlib
import (
"time"
)
// CheckMountEmpty checks if mountpoint folder is empty.
// On non-Linux unixes we list directory to ensure that.
func CheckMountEmpty(mountpoint string) error {
@@ -19,9 +15,5 @@ func CheckMountReady(mountpoint string) error {
return nil
}
// WaitMountReady should wait until mountpoint is mounted by rclone.
// The check is implemented only for Linux so we just sleep a little.
func WaitMountReady(mountpoint string, timeout time.Duration) error {
time.Sleep(timeout)
return nil
}
// CanCheckMountReady is set if CheckMountReady is functional
var CanCheckMountReady = false

View File

@@ -10,7 +10,6 @@ import (
"runtime"
"strings"
"sync"
"syscall"
"time"
"github.com/rclone/rclone/cmd"
@@ -157,6 +156,38 @@ func AddFlags(flagSet *pflag.FlagSet) {
flags.DurationVarP(flagSet, &Opt.DaemonWait, "daemon-wait", "", Opt.DaemonWait, "Time to wait for ready mount from daemon (maximum time on Linux, constant sleep time on OSX/BSD) (not supported on Windows)", "Mount")
}
const (
pollInterval = 100 * time.Millisecond
)
// WaitMountReady waits until mountpoint is mounted by rclone.
//
// If the mount daemon dies prematurely it will notice too.
func WaitMountReady(mountpoint string, timeout time.Duration, daemon *os.Process) (err error) {
endTime := time.Now().Add(timeout)
for {
if CanCheckMountReady {
err = CheckMountReady(mountpoint)
if err == nil {
break
}
}
err = daemonize.Check(daemon)
if err != nil {
return err
}
delay := time.Until(endTime)
if delay <= 0 {
break
}
if delay > pollInterval {
delay = pollInterval
}
time.Sleep(delay)
}
return
}
// NewMountCommand makes a mount command with the given name and Mount function
func NewMountCommand(commandName string, hidden bool, mount MountFn) *cobra.Command {
var commandDefinition = &cobra.Command{
@@ -220,16 +251,9 @@ func NewMountCommand(commandName string, hidden bool, mount MountFn) *cobra.Comm
handle := atexit.Register(func() {
killDaemon("Got interrupt")
})
err = WaitMountReady(mnt.MountPoint, Opt.DaemonWait)
err = WaitMountReady(mnt.MountPoint, Opt.DaemonWait, daemon)
if err != nil {
killDaemon("Daemon timed out")
} else {
// Double check daemon is still alive
// on non Linux OSes WaitMountReady is just a no-op
err = daemon.Signal(syscall.Signal(0))
if err != nil {
err = fmt.Errorf("daemon has died: %w", err)
}
}
atexit.Unregister(handle)
}