mount: fix --daemon failing when --rc is enabled - fixes #9196

Before this change the parent process kept the remote control and
metrics servers it started in initConfig listening, so the daemon child
could not bind the same addresses and exited.

After this change the parent shuts those servers down just before
daemonizing, and the child starts them as usual.
This commit is contained in:
somaz authored and Nick Craig-Wood committed 2026-10-08 14:19:18 +01:00
1 parent c5112be66b
commit 4532a88838
3 files changed
+79 -2

No files matched your search

+23 -2
View File
@@ -379,6 +379,27 @@ func StartStats() func() {
}
}
var (
rcServer *rcserver.Server
metricsServer *rcserver.MetricsServer
)
// StopRemoteControl shuts down the remote control and metrics servers started by initConfig.
func StopRemoteControl() {
if rcServer != nil {
if err := rcServer.Shutdown(); err != nil {
fs.Errorf(nil, "Failed to stop remote control: %v", err)
}
rcServer = nil
}
if metricsServer != nil {
if err := metricsServer.Shutdown(); err != nil {
fs.Errorf(nil, "Failed to stop metrics server: %v", err)
}
metricsServer = nil
}
}
// initConfig is run by cobra after initialising the flags
func initConfig() {
// Set the global options from the flags
@@ -422,14 +443,14 @@ func initConfig() {
}
// Start the remote control server if configured
_, err = rcserver.Start(ctx, &rc.Opt)
rcServer, err = rcserver.Start(ctx, &rc.Opt)
if err != nil {
fs.Fatalf(nil, "Failed to start remote control: %v", err)
}
// Start the metrics server if configured and not running the "rc" command
if len(os.Args) >= 2 && os.Args[1] != "rc" {
_, err = rcserver.MetricsStart(ctx, &rc.Opt)
metricsServer, err = rcserver.MetricsStart(ctx, &rc.Opt)
if err != nil {
fs.Fatalf(nil, "Failed to start metrics server: %v", err)
}
+52
View File
@@ -0,0 +1,52 @@
package cmd
import (
"context"
"net"
"testing"
"github.com/rclone/rclone/fs/rc"
"github.com/rclone/rclone/fs/rc/rcserver"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func freeAddr(t *testing.T) string {
l, err := net.Listen("tcp", "127.0.0.1:0")
require.NoError(t, err)
addr := l.Addr().String()
require.NoError(t, l.Close())
return addr
}
func TestStopRemoteControl(t *testing.T) {
ctx := context.Background()
rcAddr, metricsAddr := freeAddr(t), freeAddr(t)
opt := rc.Opt
opt.Enabled = true
opt.HTTP.ListenAddr = []string{rcAddr}
opt.MetricsHTTP.ListenAddr = []string{metricsAddr}
var err error
rcServer, err = rcserver.Start(ctx, &opt)
require.NoError(t, err)
metricsServer, err = rcserver.MetricsStart(ctx, &opt)
require.NoError(t, err)
require.NotNil(t, rcServer)
require.NotNil(t, metricsServer)
for _, addr := range []string{rcAddr, metricsAddr} {
_, err := net.Listen("tcp", addr)
require.Error(t, err, "%s should be in use while the servers run", addr)
}
StopRemoteControl()
assert.Nil(t, rcServer)
assert.Nil(t, metricsServer)
for _, addr := range []string{rcAddr, metricsAddr} {
l, err := net.Listen("tcp", addr)
require.NoError(t, err, "%s should be free after StopRemoteControl", addr)
require.NoError(t, l.Close())
}
}
+4
View File
@@ -309,6 +309,10 @@ func NewMountCommand(commandName string, hidden bool, mount MountFn) *cobra.Comm
if Opt.Daemon {
config.PassConfigKeyForDaemonization = true
if !fs.IsDaemon() {
// The daemon child starts these servers on the same addresses
cmd.StopRemoteControl()
}
}
if os.Getenv("PATH") == "" && runtime.GOOS != "windows" {