Fixes DisableAutoConnect semantics

DisableAutoConnect semantics
============================

Scope: governs ONLY the service-Start auto-connect decision. Once the
connection goroutine has been spawned (by any path), the flag is never
consulted again — the retry loop keeps trying to connect until ctx is
cancelled by Down / Stop / Logout.

Cases
-----

1. Service Start + DisableAutoConnect = true
   - No connection goroutine spawned.
   - clientRunning stays false.
   - State set to StatusIdle.
   - Daemon stays passive until an explicit Up RPC.

2. Service Start + DisableAutoConnect = false
   - Spawn connectWithRetryRuns.
   - clientRunning = true.
   - Retry loop runs until ctx cancelled.

3. Up RPC (any value of DisableAutoConnect)
   - Flag ignored. The user / admin explicitly asked to connect — by
     definition not "auto".
   - Spawn connectWithRetryRuns.
   - clientRunning = true.

4. MDM-triggered restart (any value of DisableAutoConnect)
   - Flag ignored. An MDM policy change applies new config to an
     already-running engine; treated as an implicit Up.
   - Spawn connectWithRetryRuns.
   - clientRunning = true.

5. Down / Stop / Logout
   - Cancels ctx → connectWithRetryRuns exits → close(giveUpChan).
   - cleanupConnection clears clientRunning = false.
   - DisableAutoConnect not involved.
Prepare for next step

Collapse error log into s.connect and rename it to more explicit connectOnce

# Conflicts:
#	client/server/server.go
This commit is contained in:
riccardom
2026-06-10 14:30:02 +02:00
parent a45cefe57a
commit 4abb10c1aa

View File

@@ -243,16 +243,20 @@ func (s *Server) Start() error {
// connectWithRetryRuns runs the client connection with a backoff strategy where we retry the operation as additional
// mechanism to keep the client connected even when the connection is lost.
// we cancel retry if the client receive a stop or down command, or if disable auto connect is configured.
// we cancel retry if the client receive a stop or down command.
//
// DisableAutoConnect governs ONLY the service-Start auto-connect decision
// (handled in Start). Once this goroutine is spawned — by Start, Up or an
// MDM restart — the flag is never consulted again: the retry loop keeps
// trying until ctx is cancelled by Down / Stop / Logout.
//
// The goroutine's exit is signalled to the daemon via close(giveUpChan)
// — placed in the function-scope defer so every return path (panic,
// DisableAutoConnect early-exit, backoff exhausted, ctx cancel) closes
// it. Callers that need to observe "is the goroutine still alive?" use
// Server.connectionGoroutineRunning() which non-blockingly checks the close state
// of clientGiveUpChan. The defer does NOT touch s.mutex; the daemon's
// "intent" (clientRunning) is maintained by the RPC handlers, not by this
// goroutine.
// backoff exhausted, ctx cancel) closes it. Callers that need to observe
// "is the goroutine still alive?" use Server.connectionGoroutineRunning()
// which non-blockingly checks the close state of clientGiveUpChan. The defer
// does NOT touch s.mutex; the daemon's "intent" (clientRunning) is maintained
// by the RPC handlers, not by this goroutine.
func (s *Server) connectWithRetryRuns(ctx context.Context, client *internal.ConnectClient, profileConfig *profilemanager.Config, statusRecorder *peer.Status, runningChan chan struct{}, giveUpChan chan struct{}) {
defer func() {
if giveUpChan != nil {
@@ -260,14 +264,6 @@ func (s *Server) connectWithRetryRuns(ctx context.Context, client *internal.Conn
}
}()
if s.config.DisableAutoConnect {
if err := s.connect(client, s.config, runningChan); err != nil {
log.Debugf("run client connection exited with error: %v", err)
}
log.Tracef("client connection exited")
return
}
backOff := getConnectWithBackoff(ctx)
go func() {
t := time.NewTicker(24 * time.Hour)
@@ -290,9 +286,9 @@ func (s *Server) connectWithRetryRuns(ctx context.Context, client *internal.Conn
}()
runOperation := func() error {
err := s.connect(client, profileConfig, runningChan)
err := s.connectOnce(client, profileConfig, runningChan)
if err != nil {
log.Debugf("run client connection exited with error: %v. Will retry in the background", err)
log.Debugf("will retry the connection in the background")
return err
}
@@ -1738,9 +1734,13 @@ func (s *Server) GetFeatures(ctx context.Context, msg *proto.GetFeaturesRequest)
return features, nil
}
func (s *Server) connect(client *internal.ConnectClient, config *profilemanager.Config, runningChan chan struct{}) error {
// connectOnce performs a single client run (Run blocks, retrying its own
// internal backoff, until the run ends). The outer connectWithRetryRuns
// backoff re-invokes it only when a run returns an error.
func (s *Server) connectOnce(client *internal.ConnectClient, config *profilemanager.Config, runningChan chan struct{}) error {
log.Tracef("running client connection")
if err := client.Run(config, runningChan, s.logFile); err != nil {
log.Debugf("run client connection exited with error: %v", err)
return err
}
return nil