From 7066c3cca306156cd188f49c6e9146993358dce4 Mon Sep 17 00:00:00 2001 From: Vikram bir Singh Date: Mon, 20 Jul 2026 16:36:48 -0700 Subject: [PATCH] fix(initsystem): don't fail WinSCM start/stop/restart on benign slow-start warning When a Windows service stays in StartPending/StopPending for a moment (common on a cold first start), Start-Service/Stop-Service/Restart-Service emit a non-terminating "Waiting for service '...' to start/stop..." warning. That goes to the warning stream, which lands on stderr under a subprocess, and rig treats any Windows stderr output as a failure (ErrWroteStderr) unless AllowWinStderr is set. So a successful-but-slow start was reported as a failure. Add -WarningAction SilentlyContinue to the three cmdlets. This silences exactly the benign progress warning while -ErrorAction Stop still turns a genuine failure into a terminating (non-zero) error, so real error detection is preserved. Uses -WarningAction only, not AllowWinStderr, which would greenlight any stderr output and could mask unexpected diagnostics. Fixes #404 Signed-off-by: Vikram bir Singh Co-Authored-By: Claude Opus 4.8 (1M context) --- initsystem/winscm.go | 22 +++++++++++++++++++--- initsystem/winscm_test.go | 7 +++++++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/initsystem/winscm.go b/initsystem/winscm.go index 323efca8..93fb4678 100644 --- a/initsystem/winscm.go +++ b/initsystem/winscm.go @@ -20,16 +20,28 @@ type WinSCM struct{} func (WinSCM) String() string { return "winscm" } // StartService starts a service. +// +// -WarningAction SilentlyContinue suppresses the benign "Waiting for service +// '…' to start..." progress warning that Start-Service emits when a service +// stays in StartPending for a moment (common on a cold first start). That +// warning goes to the warning stream, which lands on stderr under a subprocess, +// and rig treats any Windows stderr output as a failure. -ErrorAction Stop +// still turns a genuine start failure into a terminating (non-zero) error, so +// real failures are still detected. func (c WinSCM) StartService(ctx context.Context, h cmd.ContextRunner, s string) error { - if err := h.ExecContext(ctx, "$ErrorActionPreference='Stop'\nStart-Service "+ps.SingleQuote(s)+" -ErrorAction Stop", cmd.PS()); err != nil { + if err := h.ExecContext(ctx, "$ErrorActionPreference='Stop'\nStart-Service "+ps.SingleQuote(s)+" -ErrorAction Stop -WarningAction SilentlyContinue", cmd.PS()); err != nil { return fmt.Errorf("failed to start service %s: %w", s, err) } return nil } // StopService stops a service. +// +// -WarningAction SilentlyContinue suppresses the benign "Waiting for service +// '…' to stop..." progress warning (StopPending) for the same reason as +// StartService; -ErrorAction Stop still surfaces genuine failures. func (c WinSCM) StopService(ctx context.Context, h cmd.ContextRunner, s string) error { - if err := h.ExecContext(ctx, "$ErrorActionPreference='Stop'\nStop-Service "+ps.SingleQuote(s)+" -ErrorAction Stop", cmd.PS()); err != nil { + if err := h.ExecContext(ctx, "$ErrorActionPreference='Stop'\nStop-Service "+ps.SingleQuote(s)+" -ErrorAction Stop -WarningAction SilentlyContinue", cmd.PS()); err != nil { return fmt.Errorf("failed to stop service %s: %w", s, err) } return nil @@ -41,8 +53,12 @@ func (c WinSCM) ServiceScriptPath(_ context.Context, _ cmd.ContextRunner, _ stri } // RestartService restarts a service. +// +// -WarningAction SilentlyContinue suppresses the benign "Waiting for service +// '…' to start/stop..." progress warnings for the same reason as StartService; +// -ErrorAction Stop still surfaces genuine failures. func (c WinSCM) RestartService(ctx context.Context, h cmd.ContextRunner, s string) error { - if err := h.ExecContext(ctx, "$ErrorActionPreference='Stop'\nRestart-Service "+ps.SingleQuote(s)+" -ErrorAction Stop", cmd.PS()); err != nil { + if err := h.ExecContext(ctx, "$ErrorActionPreference='Stop'\nRestart-Service "+ps.SingleQuote(s)+" -ErrorAction Stop -WarningAction SilentlyContinue", cmd.PS()); err != nil { return fmt.Errorf("failed to restart service %s: %w", s, err) } return nil diff --git a/initsystem/winscm_test.go b/initsystem/winscm_test.go index 3d528dce..1098a275 100644 --- a/initsystem/winscm_test.go +++ b/initsystem/winscm_test.go @@ -45,6 +45,9 @@ func TestWinSCMStartService(t *testing.T) { script := decodePSCmd(t, mr.LastCommand()) require.Contains(t, script, "Start-Service") require.Contains(t, script, "-ErrorAction Stop") + // Suppresses the benign StartPending progress warning that otherwise + // lands on stderr and trips ErrWroteStderr on a slow/cold start. + require.Contains(t, script, "-WarningAction SilentlyContinue") require.Contains(t, script, "'myservice'") }) t.Run("failure", func(t *testing.T) { @@ -63,6 +66,8 @@ func TestWinSCMStopService(t *testing.T) { script := decodePSCmd(t, mr.LastCommand()) require.Contains(t, script, "Stop-Service") require.Contains(t, script, "-ErrorAction Stop") + // Suppresses the benign StopPending progress warning (see StartService). + require.Contains(t, script, "-WarningAction SilentlyContinue") require.Contains(t, script, "'myservice'") }) t.Run("failure", func(t *testing.T) { @@ -81,6 +86,8 @@ func TestWinSCMRestartService(t *testing.T) { script := decodePSCmd(t, mr.LastCommand()) require.Contains(t, script, "Restart-Service") require.Contains(t, script, "-ErrorAction Stop") + // Suppresses the benign start/stop progress warnings (see StartService). + require.Contains(t, script, "-WarningAction SilentlyContinue") require.Contains(t, script, "'myservice'") }) t.Run("failure", func(t *testing.T) {