shirou / gopsutil

psutil for golang
Other
10.28k stars 1.56k forks source link

Windows interrupt signal errror #1633

Closed cicada-lewis closed 2 months ago

cicada-lewis commented 2 months ago

Describe the bug

Hi, although I know golang from official doesn't support send interrupt signal on windows, I still tried it by gopsutil. It works like my domo as follow, it's so wired, and I don't know why gopsutil SendSignal return an error (Not implement yet). I wanna do gracefully exit in my child process, child process will listen interrupt signal, and father process will send it, and I ignored “Not implement yet” error just print it. And it works on win11 and win7, I didn't try it on another windows version, it is so wired. Could you please explain why set “Not implement yet” for SendSignal on windows and how it works? many thx.

To Reproduce

// child.go
package main

import (
    "fmt"
    "os"
    "os/signal"
    "syscall"
    "time"
)

func main() {
    ch := make(chan os.Signal, 1)
    signal.Notify(ch, os.Interrupt, syscall.SIGKILL, syscall.SIGTERM) // listen interrupt and others

    go func() {
        time.Sleep(10 * time.Second) 
        GracefullExit(ch)
    }()

    for {
        s := <-ch  // accept signal
        switch s {
        case syscall.SIGINT:
                        // deal with sigint
            fmt.Println("SIGINT", "graceful exit")
            time.Sleep(5 * time.Second)
            fmt.Println("system end")
            os.Exit(2)
        case syscall.SIGKILL:
            fmt.Println("SIGKILL")
        default:
            fmt.Println("get signal ", s)
            os.Exit(3)
        }
    }
}

func GracefullExit(ch chan os.Signal) {
    ch <- syscall.SIGINT
}

// parent.go
package main

import (
    "bytes"
    "errors"
    "fmt"
    "syscall"

    "os/exec"
    "time"

    "github.com/shirou/gopsutil/process"
)

func main() {
    cmd := exec.Command("./child.exe") // start child.exe
    outBuf := bytes.Buffer{} // accept child output 
    cmd.Stdout = &outBuf
    go func() {
        err := cmd.Run() 
        if err != nil {
            fmt.Printf("failed to execute child.exe with err %s \n", err)
            return
        }
    }()

    time.Sleep(5 * time.Second)
    fmt.Println("sending Interrupt...")

    proc, err := process.NewProcess(int32(cmd.Process.Pid))
    if err != nil {

        fmt.Println("new process err ", err)
        return 
    }
        // send it by gopsutils
    err = proc.SendSignal(syscall.SIGINT)
    if err != nil {
        fmt.Println("just print not implement! err ", err)
    }

    cmd.Wait()

    fmt.Printf("out %s, exit code %d, err %s", outBuf.String(), cmd.ProcessState.ExitCode(), err)

}

parent.go output is as follow

sending Interrupt...
just print not implement! err  not implemented yet
out SIGINT graceful exit  // prarent output child's out
system end
, exit code 2, err not implemented yet
cicada-lewis commented 2 months ago

sorry, It's a stupid question