diff --git a/cmd/gpu-turnstile/main.go b/cmd/gpu-turnstile/main.go index a4195db..940d7f4 100644 --- a/cmd/gpu-turnstile/main.go +++ b/cmd/gpu-turnstile/main.go @@ -362,6 +362,10 @@ func forceUpdateCommand(configPath string, elevatedChild bool) int { fmt.Fprintf(os.Stderr, "gpu-turnstile: cannot locate executable: %v\n", err) return 1 } + // One-shot CLI: the updater logs to stderr, never to the service's + // LOG_FILE — that file is ACL'd to the service account, and a CLI run + // has nothing worth persisting there. + cfg.LogFile = "" log, _, logCloser := newLogger(cfg) defer logCloser.Close() if cfg.AppVersion == "dev" { diff --git a/internal/control/control_windows.go b/internal/control/control_windows.go index d0a1ba1..7742cce 100644 --- a/internal/control/control_windows.go +++ b/internal/control/control_windows.go @@ -77,18 +77,16 @@ func Serve(ctx context.Context, h Handler, log *slog.Logger) error { log.Warn("control channel stopped", "err", err) return } - go func() { - // Blocks until a client connects; on process exit the - // handle goes away with everything else. A client that - // raced us and connected between CreateNamedPipe and - // ConnectNamedPipe reports ERROR_PIPE_CONNECTED — that is - // a success, not a failure. - if err := windows.ConnectNamedPipe(pipe, nil); err != nil && err != errnoPipeConnected { - windows.CloseHandle(pipe) - return - } - serveConn(&pipeConn{f: os.NewFile(uintptr(pipe), pipePath), h: pipe}, h) - }() + // Blocks until a client connects — only then is the next + // instance created, so instances are not burned without + // clients. ERROR_PIPE_CONNECTED means the client raced us + // and connected before the call: that is a success. Process + // exit reaps the blocked call on shutdown. + if err := windows.ConnectNamedPipe(pipe, nil); err != nil && err != errnoPipeConnected { + windows.CloseHandle(pipe) + continue + } + go serveConn(&pipeConn{f: os.NewFile(uintptr(pipe), pipePath), h: pipe}, h) } }() return nil