Skip to content

Commit

Permalink
Fix signal sending on Windows (#261)
Browse files Browse the repository at this point in the history
  • Loading branch information
kolesnikovae authored Jun 27, 2021
1 parent 74e1fe9 commit d94dc82
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 4 deletions.
8 changes: 5 additions & 3 deletions pkg/exec/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@ func Cli(cfg *config.Exec, args []string) error {
// isExec = false means the process is already there (pyroscope connect)
isExec := cfg.Pid == 0

if isExec && len(args) == 0 {
return errors.New("no arguments passed")
if isExec {
if len(args) == 0 {
return errors.New("no arguments passed")
}
} else if !processExists(cfg.Pid) {
return errors.New("process not found")
}
Expand Down Expand Up @@ -171,7 +173,7 @@ func Cli(cfg *config.Exec, args []string) error {
func waitForSpawnedProcessToExit(c chan os.Signal, cmd *goexec.Cmd) error {
go func() {
for s := range c {
_ = cmd.Process.Signal(s)
_ = sendSignal(cmd.Process, s)
}
}()
return cmd.Wait()
Expand Down
4 changes: 4 additions & 0 deletions pkg/exec/cli_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,7 @@ func generateCredentials(userName, groupName string) (*syscall.Credential, error
func processExists(pid int) bool {
return nil == syscall.Kill(pid, 0)
}

func sendSignal(p *os.Process, s os.Signal) error {
return p.Signal(s)
}
60 changes: 59 additions & 1 deletion pkg/exec/cli_windows.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,31 @@
package exec

import (
"fmt"
"os"
"os/exec"
"sync"
"syscall"

"golang.org/x/sys/windows"

"github.com/pyroscope-io/pyroscope/pkg/config"
)

var (
kernel32 = syscall.NewLazyDLL("kernel32.dll")
procAttachConsole = kernel32.NewProc("AttachConsole")
procFreeConsole = kernel32.NewProc("FreeConsole")
)

func performOSChecks(_ string) error {
return nil
}

func adjustCmd(_ *exec.Cmd, _ config.Exec) error {
func adjustCmd(cmd *exec.Cmd, _ config.Exec) error {
cmd.SysProcAttr = &syscall.SysProcAttr{
CreationFlags: windows.CREATE_NEW_PROCESS_GROUP,
}
return nil
}

Expand All @@ -23,3 +37,47 @@ func processExists(pid int) bool {
_ = p.Release()
return true
}

func sendSignal(p *os.Process, s os.Signal) error {
if p == nil || p.Pid == 0 {
return nil
}
if s == syscall.SIGINT {
return sendEvent(p.Pid, windows.CTRL_BREAK_EVENT)
}
return p.Kill()
}

// A process can be attached to at most one console.
// Refer to https://docs.microsoft.com/en-us/windows/console/attachconsole.
var console sync.Mutex

// Interrupt sends CTRL+BREAK signal to the command process group.
// Refer to https://github.com/golang/go/issues/6720 for details.
func sendEvent(pid int, e uint32) (err error) {
console.Lock()
defer console.Unlock()
ret, _, err := procAttachConsole.Call(uintptr(pid))
if ret == 0 && err != windows.ERROR_ACCESS_DENIED {
// A process can be attached to at most one console. If the calling
// process is already attached to a console, the error code returned is
// ERROR_ACCESS_DENIED (5). If the specified process does not have a
// console, the error code returned is ERROR_INVALID_HANDLE (6). If the
// specified process does not exist, the error code returned is
// ERROR_INVALID_PARAMETER (87).
return fmt.Errorf("AttachConsole: %w", err)
}
defer func() {
// A process can use the FreeConsole function to detach itself from its
// console. If other processes share the console, the console is not
// destroyed, but the process that called FreeConsole cannot refer to it.
// If the calling process is not already attached to a console,
// the error code returned is ERROR_INVALID_PARAMETER (87).
_, _, _ = procFreeConsole.Call()
}()
// Note on CTRL_C_EVENT: This signal cannot be generated for process
// groups. If dwProcessGroupId is nonzero, this function will succeed, but
// the CTRL+C signal will not be received by processes within the specified
// process group.
return windows.GenerateConsoleCtrlEvent(e, uint32(pid))
}

0 comments on commit d94dc82

Please sign in to comment.