mirror of
https://github.com/kemko/nomad.git
synced 2026-01-01 16:05:42 +03:00
windows: use/accept platform-specific signal for stopping agent (#26780)
On Windows, the `os.Process.Signal` method returns an error when sending `os.Interrupt` (SIGINT) because it isn't implemented. This causes test servers in the `testutil` packages to break on Windows. Use the platform specific syscalls to generate the SIGINT instead. The agent's signal handler also did not correctly handle the Ctrl-C because we were masking os.Interrupt instead of SIGINT. Fixes: https://github.com/hashicorp/nomad/issues/26775 Co-authored-by: Chris Roberts <croberts@hashicorp.com>
This commit is contained in:
@@ -240,7 +240,9 @@ func NewTestServer(t testing.TB, cb ServerConfigCallback) *TestServer {
|
||||
// Stop stops the test Nomad server, and removes the Nomad data
|
||||
// directory once we are done.
|
||||
func (s *TestServer) Stop() {
|
||||
defer func() { _ = os.RemoveAll(s.Config.DataDir) }()
|
||||
s.t.Cleanup(func() {
|
||||
_ = os.RemoveAll(s.Config.DataDir)
|
||||
})
|
||||
|
||||
// wait for the process to exit to be sure that the data dir can be
|
||||
// deleted on all platforms.
|
||||
@@ -251,7 +253,7 @@ func (s *TestServer) Stop() {
|
||||
}()
|
||||
|
||||
// kill and wait gracefully
|
||||
err := s.cmd.Process.Signal(os.Interrupt)
|
||||
err := s.gracefulStop()
|
||||
must.NoError(s.t, err)
|
||||
|
||||
select {
|
||||
|
||||
17
api/internal/testutil/server_default.go
Normal file
17
api/internal/testutil/server_default.go
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
//go:build !windows
|
||||
|
||||
package testutil
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
// gracefulStop performs a platform-specific graceful stop. On non-Windows this
|
||||
// uses the Go API for SIGINT
|
||||
func (s *TestServer) gracefulStop() error {
|
||||
err := s.cmd.Process.Signal(os.Interrupt)
|
||||
return err
|
||||
}
|
||||
37
api/internal/testutil/server_windows.go
Normal file
37
api/internal/testutil/server_windows.go
Normal file
@@ -0,0 +1,37 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
//go:build windows
|
||||
|
||||
package testutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var (
|
||||
kernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||
procSetCtrlHandler = kernel32.NewProc("SetConsoleCtrlHandler")
|
||||
procGenCtrlEvent = kernel32.NewProc("GenerateConsoleCtrlEvent")
|
||||
)
|
||||
|
||||
// gracefulStop performs a platform-specific graceful stop. On Windows the Go
|
||||
// API does not implement SIGINT even though it's supported on Windows via
|
||||
// CTRL_C_EVENT
|
||||
func (s *TestServer) gracefulStop() error {
|
||||
// note: err is always non-nil from these proc Call methods because it's
|
||||
// always populated from GetLastError and you need to check the result
|
||||
// returned against the docs.
|
||||
pid := s.cmd.Process.Pid
|
||||
result, _, err := procSetCtrlHandler.Call(0, 1)
|
||||
if result == 0 {
|
||||
return fmt.Errorf("failed to modify handlers for ctrl-c on pid %d: %w", pid, err)
|
||||
}
|
||||
|
||||
result, _, err = procGenCtrlEvent.Call(syscall.CTRL_C_EVENT, uintptr(pid))
|
||||
if result == 0 {
|
||||
return fmt.Errorf("failed to send ctrl-C event to pid %d: %w", pid, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user