diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 52bef3c3..0c7cfdf4 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -16,9 +16,12 @@ builds: goos: - linux - darwin + - windows ignore: - goos: linux goarch: '386' + - goos: windows + goarch: '386' archives: - name_template: >- @@ -27,6 +30,9 @@ archives: {{- if eq .Arch "amd64" }}x86_64 {{- else if eq .Arch "386" }}i386 {{- else }}{{ .Arch }}{{ end }} + format_overrides: + - goos: windows + formats: [ zip ] files: - LICENSE - completions/* diff --git a/cmd/project/project_worker.go b/cmd/project/project_worker.go index 31ec9a74..532c7f34 100644 --- a/cmd/project/project_worker.go +++ b/cmd/project/project_worker.go @@ -104,21 +104,7 @@ var projectWorkerCmd = &cobra.Command{ cmd.Env = append(os.Environ(), fmt.Sprintf("MESSENGER_CONSUMER_NAME=%s-%d", baseName, index)) cmd.WaitDelay = time.Second cmd.Cancel = func() error { - if gracefulStopLimit > 0 { - if err := cmd.Process.Signal(syscall.SIGTERM); err != nil { - return err - } - - now := time.Now() - - for time.Since(now) < time.Second*time.Duration(gracefulStopLimit) { - if isProcessStopped(cmd.Process) { - return os.ErrProcessDone - } - time.Sleep(time.Millisecond * 250) - } - } - return cmd.Process.Kill() + return gracefulStop(cmd, gracefulStopLimit) } if err := cmd.Run(); err != nil { @@ -157,7 +143,3 @@ func cancelOnTermination(ctx context.Context, cancel context.CancelFunc) { cancel() }() } - -func isProcessStopped(p *os.Process) bool { - return errors.Is(p.Signal(syscall.Signal(0)), os.ErrProcessDone) -} diff --git a/cmd/project/project_worker_unix.go b/cmd/project/project_worker_unix.go new file mode 100644 index 00000000..06a50507 --- /dev/null +++ b/cmd/project/project_worker_unix.go @@ -0,0 +1,34 @@ +//go:build !windows + +package project + +import ( + "errors" + "os" + "os/exec" + "syscall" + "time" +) + +// gracefulStop sends SIGTERM and waits up to gracefulStopLimit seconds for the process to exit before killing it. A limit of 0 kills immediately. +func gracefulStop(cmd *exec.Cmd, gracefulStopLimit uint) error { + if gracefulStopLimit > 0 { + if err := cmd.Process.Signal(syscall.SIGTERM); err != nil { + return err + } + + deadline := time.Now().Add(time.Second * time.Duration(gracefulStopLimit)) + for time.Now().Before(deadline) { + if isProcessStopped(cmd.Process) { + return os.ErrProcessDone + } + time.Sleep(time.Millisecond * 250) + } + } + + return cmd.Process.Kill() +} + +func isProcessStopped(p *os.Process) bool { + return errors.Is(p.Signal(syscall.Signal(0)), os.ErrProcessDone) +} diff --git a/cmd/project/project_worker_windows.go b/cmd/project/project_worker_windows.go new file mode 100644 index 00000000..4deefcc4 --- /dev/null +++ b/cmd/project/project_worker_windows.go @@ -0,0 +1,10 @@ +//go:build windows + +package project + +import "os/exec" + +// gracefulStop kills the process immediately. Windows console child processes cannot receive SIGTERM, so graceful termination is not possible; +func gracefulStop(cmd *exec.Cmd, _ uint) error { + return cmd.Process.Kill() +}