Rename to clarify

This commit is contained in:
riccardom
2026-06-18 14:40:03 +02:00
parent 5d7cb30e5b
commit 6d3bcef2c4
3 changed files with 29 additions and 44 deletions
+8 -15
View File
@@ -472,26 +472,19 @@ func parseRelayInfo(loginResp *mgmProto.LoginResponse) ([]string, *hmac.Token) {
return relayCfg.GetUrls(), token return relayCfg.GetUrls(), token
} }
// IsRunning reports whether a client run is currently in flight. It is the // ConnectionRunning reports whether a connection run is currently in flight
// single source of truth for "is the client running", answered by the // (connecting, connected, or reconnecting). Answered by the supervisor via a
// supervisor via a serialized query (so it settles behind an in-flight stop). // serialized query, so it settles behind an in-flight stop. Distinct from
// Intended for the external status surface (CLI/UI), not internal pre-checks. // ServiceRunning, which reports whether the service itself is alive.
func (c *ConnectClient) IsRunning() bool { func (c *ConnectClient) ConnectionRunning() bool {
if c == nil || c.sup == nil {
return false
}
return c.sup.isRunning() return c.sup.isRunning()
} }
// ServiceRunning reports whether the client's lifecycle supervisor is alive and // ServiceRunning reports whether the client's lifecycle supervisor is alive and
// able to accept start/stop commands — i.e. the daemon-lifetime client exists // able to accept start/stop commands — i.e. its context has not been cancelled
// and its context has not been cancelled. It is independent of whether a run is // (the daemon is not shutting down). Independent of whether a connection run is
// currently up (that is IsRunning). Nil-safe, so callers can ask it on a // up (that is ConnectionRunning).
// not-yet-constructed client and treat false as "service not running".
func (c *ConnectClient) ServiceRunning() bool { func (c *ConnectClient) ServiceRunning() bool {
if c == nil || c.sup == nil {
return false
}
return c.sup.ctx.Err() == nil return c.sup.ctx.Err() == nil
} }
+13 -19
View File
@@ -38,12 +38,11 @@ type conflictCheck struct {
// OS-native managed-config store reports a diff vs the last observation. // OS-native managed-config store reports a diff vs the last observation.
// //
// Restart sequence: // Restart sequence:
// 1. Cancel the active engine context (terminates connectWithRetryRuns). // 1. Stop the in-flight run via the supervisor (blocks until fully torn down).
// 2. Wait briefly for that goroutine to exit (giveUpChan is closed on exit). // 2. Re-resolve Config from disk + MDM policy (Config.apply re-runs
// 3. Re-resolve Config from disk + MDM policy (Config.apply re-runs
// applyMDMPolicy with the freshly loaded Policy). // applyMDMPolicy with the freshly loaded Policy).
// 4. Spawn a fresh connectWithRetryRuns with the new context and config. // 3. Start a fresh run with the new config.
// 5. Broadcast a SystemEvent so any GUI / CLI subscriber (SubscribeEvents // 4. Broadcast a SystemEvent so any GUI / CLI subscriber (SubscribeEvents
// RPC) can refresh its cached config view without polling. // RPC) can refresh its cached config view without polling.
// //
// The callback runs in the ticker's own goroutine. Ticker has already // The callback runs in the ticker's own goroutine. Ticker has already
@@ -51,17 +50,13 @@ type conflictCheck struct {
func (s *Server) onMDMPolicyChange(_, _ *mdm.Policy) error { func (s *Server) onMDMPolicyChange(_, _ *mdm.Policy) error {
log.Warn("MDM policy changed; restarting engine to apply new configuration") log.Warn("MDM policy changed; restarting engine to apply new configuration")
// Hold s.mutex for the entire restart sequence (cancel + quiescence // Hold s.mutex for the entire restart sequence (stop + re-start). Any
// wait + re-spawn). Any concurrent Up/Down/Status arriving while // concurrent Up/Down/Status arriving while MDM is restarting blocks on the
// MDM is restarting blocks on the Lock until we are done — they // Lock until we are done — they then observe the post-restart state coherently.
// then observe the post-restart state coherently. This is safe
// because the connectWithRetryRuns goroutine no longer acquires
// s.mutex in its defer (intent vs. goroutine-alive concerns are
// fully separated; see the connectionGoroutineRunning helper).
s.mutex.Lock() s.mutex.Lock()
defer s.mutex.Unlock() defer s.mutex.Unlock()
if !s.connectClient.IsRunning() { if !s.connectClient.ConnectionRunning() {
// No run in flight, so there's no engine to restart. // No run in flight, so there's no engine to restart.
return nil return nil
} }
@@ -123,14 +118,13 @@ func (s *Server) publishConfigChangedEvent(source string) {
} }
// restartEngineForMDMLocked re-resolves the active profile config // restartEngineForMDMLocked re-resolves the active profile config
// (re-running applyMDMPolicy via Config.apply) and re-spawns // (re-running applyMDMPolicy via Config.apply) and starts a fresh run.
// connectWithRetryRuns. Mirrors the tail of Server.Start so a runtime // Mirrors the tail of Server.Start so a runtime MDM change behaves
// MDM change behaves identically to a fresh boot under the new policy. // identically to a fresh boot under the new policy.
// //
// MUST be called with s.mutex held — onMDMPolicyChange holds the lock // MUST be called with s.mutex held — onMDMPolicyChange holds the lock
// for the entire restart sequence (cancel + quiescence wait + re-spawn) // for the entire restart sequence so concurrent Up/Down/Status RPCs
// so concurrent Up/Down/Status RPCs observe a coherent post-restart // observe a coherent post-restart state.
// state.
func (s *Server) restartEngineForMDMLocked() error { func (s *Server) restartEngineForMDMLocked() error {
activeProf, err := s.profileManager.GetActiveProfileState() activeProf, err := s.profileManager.GetActiveProfileState()
if err != nil { if err != nil {
+8 -10
View File
@@ -63,7 +63,7 @@ type Server struct {
config *profilemanager.Config config *profilemanager.Config
proto.UnimplementedDaemonServiceServer proto.UnimplementedDaemonServiceServer
// Whether a run is in flight is owned by the supervisor // Whether a run is in flight is owned by the supervisor
// (connectClient.IsRunning); the daemon keeps no separate "running" flag. // (connectClient.ConnectionRunning); the daemon keeps no separate flag.
clientRunningChan chan struct{} // closed by the run when the engine is ready clientRunningChan chan struct{} // closed by the run when the engine is ready
clientDoneChan chan error // receives the run's end result clientDoneChan chan error // receives the run's end result
@@ -139,7 +139,7 @@ func (s *Server) Start() error {
s.mutex.Lock() s.mutex.Lock()
defer s.mutex.Unlock() defer s.mutex.Unlock()
if s.connectClient.IsRunning() { if s.connectClient.ConnectionRunning() {
return nil return nil
} }
@@ -665,11 +665,9 @@ func (s *Server) Up(callerCtx context.Context, msg *proto.UpRequest) (*proto.UpR
return nil, fmt.Errorf("service is not running, start the netbird service for 'up' to take effect") return nil, fmt.Errorf("service is not running, start the netbird service for 'up' to take effect")
} }
// clientRunning is the daemon-intent flag (set by previous Up/Start, cleared // If a connection run is already in flight, the existing engine is on the
// by Down). IsRunning() reports whether a run is actually in flight. When // job — just wait for it. Otherwise fall through to start a fresh run.
// intent is up AND a run is in flight, the existing engine is on the job — if s.connectClient.ConnectionRunning() {
// just wait for it. Otherwise fall through to start a fresh run.
if s.connectClient.IsRunning() {
state := internal.CtxGetState(s.rootCtx) state := internal.CtxGetState(s.rootCtx)
status, err := state.Status() status, err := state.Status()
if err != nil { if err != nil {
@@ -1029,7 +1027,7 @@ func (s *Server) validateProfileOperation(profileName string, allowActiveProfile
// logoutFromProfile logs out from a specific profile by loading its config and sending logout request // logoutFromProfile logs out from a specific profile by loading its config and sending logout request
func (s *Server) logoutFromProfile(ctx context.Context, profileName, username string) error { func (s *Server) logoutFromProfile(ctx context.Context, profileName, username string) error {
activeProf, err := s.profileManager.GetActiveProfileState() activeProf, err := s.profileManager.GetActiveProfileState()
if err == nil && activeProf.Name == profileName && s.connectClient.IsRunning() { if err == nil && activeProf.Name == profileName && s.connectClient.ConnectionRunning() {
return s.sendLogoutRequest(ctx) return s.sendLogoutRequest(ctx)
} }
@@ -1087,7 +1085,7 @@ func (s *Server) Status(
runningChan := s.clientRunningChan runningChan := s.clientRunningChan
doneChan := s.clientDoneChan doneChan := s.clientDoneChan
s.mutex.Unlock() s.mutex.Unlock()
alive := client != nil && client.IsRunning() alive := client.ConnectionRunning()
if msg.WaitForReady != nil && *msg.WaitForReady && alive { if msg.WaitForReady != nil && *msg.WaitForReady && alive {
select { select {
@@ -1335,7 +1333,7 @@ func (s *Server) WaitJWTToken(
// ExposeService exposes a local port via the NetBird reverse proxy. // ExposeService exposes a local port via the NetBird reverse proxy.
func (s *Server) ExposeService(req *proto.ExposeServiceRequest, srv proto.DaemonService_ExposeServiceServer) error { func (s *Server) ExposeService(req *proto.ExposeServiceRequest, srv proto.DaemonService_ExposeServiceServer) error {
s.mutex.Lock() s.mutex.Lock()
if !s.connectClient.IsRunning() { if !s.connectClient.ConnectionRunning() {
s.mutex.Unlock() s.mutex.Unlock()
return gstatus.Errorf(codes.FailedPrecondition, "client is not running, run 'netbird up' first") return gstatus.Errorf(codes.FailedPrecondition, "client is not running, run 'netbird up' first")
} }