Browse code

daemon: send systemd READY=1 after API serve loops start

The daemon previously signaled systemd (READY=1) before the API Serve loops
were started.

Move the readiness notification until after the API listeners are serving
to reduce the window where systemd considers the daemon ready but the
HTTP accept loop has not yet started.

While modifying, also use `WaitGroup.Go` for a slight cleanup.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

Sebastiaan van Stijn authored on 2026/02/22 03:12:43
Showing 1 changed files
... ...
@@ -345,22 +345,22 @@ func (cli *daemonCLI) start(ctx context.Context) (err error) {
345 345
 
346 346
 	cli.setupConfigReloadTrap()
347 347
 
348
-	// after the daemon is done setting up we can notify systemd api
349
-	notifyReady()
350 348
 	log.G(ctx).Info("Daemon has completed initialization")
351 349
 
352 350
 	// Daemon is fully initialized. Start handling API traffic
353 351
 	// and wait for serve API to complete.
354 352
 	var (
355
-		apiWG  sync.WaitGroup
356
-		errAPI = make(chan error, 1)
353
+		apiWG      sync.WaitGroup
354
+		errAPI     = make(chan error, 1)
355
+		apiStartWG sync.WaitGroup
357 356
 	)
357
+
358
+	apiStartWG.Add(len(lss))
358 359
 	for _, ls := range lss {
359
-		apiWG.Add(1)
360
-		go func(ls net.Listener) {
361
-			defer apiWG.Done()
360
+		apiWG.Go(func() {
362 361
 			log.G(ctx).Infof("API listen on %s", ls.Addr())
363
-			if err := httpServer.Serve(ls); err != http.ErrServerClosed {
362
+			apiStartWG.Done()
363
+			if err := httpServer.Serve(ls); err != nil && !errors.Is(err, http.ErrServerClosed) {
364 364
 				log.G(ctx).WithFields(log.Fields{
365 365
 					"error":    err,
366 366
 					"listener": ls.Addr(),
... ...
@@ -371,8 +371,20 @@ func (cli *daemonCLI) start(ctx context.Context) (err error) {
371 371
 				default:
372 372
 				}
373 373
 			}
374
-		}(ls)
374
+		})
375 375
 	}
376
+
377
+	// Wait for all API listeners to start handling requests.
378
+	apiStartWG.Wait()
379
+
380
+	select {
381
+	case <-errAPI:
382
+		// An API listener failed to start; skip notifying systemd that we're ready.
383
+	default:
384
+		// All API listeners started handling requests; notify systemd that we're ready.
385
+		notifyReady()
386
+	}
387
+
376 388
 	apiWG.Wait()
377 389
 	close(errAPI)
378 390