From 1a80fa4098fdcf4922b9604c8ea685ff0df2376f Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Fri, 2 Oct 2026 14:19:18 +0200 Subject: [PATCH] daemon: make Windows service unregistration idempotent Treat an already absent service or one already marked for deletion as a successful unregister operation. Continue removing the event log registration in those cases so retries also clean up stale registration state left by an earlier partial unregister. Signed-off-by: Sebastiaan van Stijn --- daemon/command/service_windows.go | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/daemon/command/service_windows.go b/daemon/command/service_windows.go index 6bfad72be9..7895e414ce 100644 --- a/daemon/command/service_windows.go +++ b/daemon/command/service_windows.go @@ -200,6 +200,9 @@ func registerService() (retErr error) { return eventlog.Install(*flServiceName, p, false, eventlog.Info|eventlog.Warning|eventlog.Error) } +// unregisterService unregisters the Docker Windows service and removes its +// event log registration. It succeeds if the service is already absent or +// already marked for deletion. func unregisterService() error { m, err := mgr.Connect() if err != nil { @@ -208,12 +211,16 @@ func unregisterService() error { defer m.Disconnect() s, err := m.OpenService(*flServiceName) - if err != nil { - return err - } - defer s.Close() + switch { + case err == nil: + defer s.Close() - if err := s.Delete(); err != nil { + if err := s.Delete(); err != nil && !errors.Is(err, windows.ERROR_SERVICE_MARKED_FOR_DELETE) { + return err + } + case errors.Is(err, windows.ERROR_SERVICE_DOES_NOT_EXIST): + // Continue to remove a potentially stale event log registration. + default: return err } if err := eventlog.Remove(*flServiceName); err != nil && !errors.Is(err, registry.ErrNotExist) {