确保在进程被终止时,Go Process中调用的可执行文件被终止

时间:2016-01-11 20:58:10

标签: go

我有一些代码在Go(golang)中,有几个不同的线程运行一个单独的可执行文件。我想确保如果用户在Go中杀死我的进程,我有办法杀死我所称的可执行文件,有没有办法做到这一点?

5 个答案:

答案 0 :(得分:5)

确保子进程被终止的唯一方法是在同一进程组中启动它,并将进程组作为一个整体终止,或者在syscall.SetProcAddr中设置Pdeadthsig。 / p>

您可以为SIG_INTSIG_TERM之类的常见信号设置信号处理程序,并在退出之前终止您的子进程,但是因为您无法抓住SIG_KILL那个&#39}经常不值得努力。

请参阅:Panic in other goroutine not stopping child process

cmd := exec.Command("./long-process")

cmd.SysProcAttr = &syscall.SysProcAttr{
    Pdeathsig: syscall.SIGTERM,
}

答案 1 :(得分:1)

一种可能的策略是在全局数组var childProcesses = make([]*os.Process, 0)中保留正在运行的进程的列表,并在每次启动进程时将其追加到列表中。

具有自己的Exit函数。确保不要在代码中的任何地方调用os.Exit,而应始终调用自己的Exit函数。您的退出函数将杀死所有childProcesses

for _, p := range childProcesses {
    p.Kill()
}

处理信号,以便它们通过您自己的退出函数,例如,在初始化过程中执行此操作(在主函数顶部附近)

sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM, syscall.SIGKILL, syscall.SIGQUIT)
goUnsafe(func() {
    var signal = <-sigs
    log.Println("Got Signal", signal)
    Exit(0)
})

答案 2 :(得分:0)

我建议你使用unix.Prctl。

flag := unix.SIGHUP
if err := unix.Prctl(unix.PR_SET_PDEATHSIG, uintptr(flag), 0, 0, 0); err != nil {
    return
}

下面是一个详细的例子,new.go用于子进程,main.go用作父进程。

//new.go
package main

func main() {
    flag := unix.SIGHUP

    if err := unix.Prctl(unix.PR_SET_PDEATHSIG, uintptr(flag), 0, 0, 0); err != nil {
    return
    }

    f, _ := os.Create("./dat2")
    defer f.Close()
    i := 0
    for {
        n3, _ := f.WriteString("writes " + string(i) + "\n")
        fmt.Printf("wrote %d bytes\n", n3)
        f.Sync()
        i += 2
        time.Sleep(2 * time.Second)
    }

    for {
        n3, _ := f.WriteString("newwrites\n")
        fmt.Printf("wrote %d bytes\n", n3)
        f.Sync()
        time.Sleep(2 * time.Second)
    }
}


//main.go
package main

import "os/exec"

func main() {
    commandA := exec.Command("./new")
    commandA.Start()
    commandB := exec.Command("./new")
    commandB.Start()
    for {
    }
}

答案 3 :(得分:0)

如果您使用的是Windows,则此片段可能会有所帮助:

package main

import (
    "os"
    "os/exec"
    "unsafe"

    "golang.org/x/sys/windows"
)

// We use this struct to retreive process handle(which is unexported)
// from os.Process using unsafe operation.
type process struct {
    Pid    int
    Handle uintptr
}

type ProcessExitGroup windows.Handle

func NewProcessExitGroup() (ProcessExitGroup, error) {
    handle, err := windows.CreateJobObject(nil, nil)
    if err != nil {
        return 0, err
    }

    info := windows.JOBOBJECT_EXTENDED_LIMIT_INFORMATION{
        BasicLimitInformation: windows.JOBOBJECT_BASIC_LIMIT_INFORMATION{
            LimitFlags: windows.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE,
        },
    }
    if _, err := windows.SetInformationJobObject(
        handle,
        windows.JobObjectExtendedLimitInformation,
        uintptr(unsafe.Pointer(&info)),
        uint32(unsafe.Sizeof(info))); err != nil {
        return 0, err
    }

    return ProcessExitGroup(handle), nil
}

func (g ProcessExitGroup) Dispose() error {
    return windows.CloseHandle(windows.Handle(g))
}

func (g ProcessExitGroup) AddProcess(p *os.Process) error {
    return windows.AssignProcessToJobObject(
        windows.Handle(g),
        windows.Handle((*process)(unsafe.Pointer(p)).Handle))
}

func main() {
    g, err := NewProcessExitGroup()
    if err != nil {
        panic(err)
    }
    defer g.Dispose()

    cmd := exec.Command("notepad.exe", "noname")
    if err := cmd.Start(); err != nil {
        panic(err)
    }

    if err := g.AddProcess(cmd.Process); err != nil {
        panic(err)
    }

    if err := cmd.Wait(); err != nil {
        panic(err)
    }
}

原始链接:https://gist.github.com/hallazzang/76f3970bfc949831808bbebc8ca15209

答案 4 :(得分:0)

  

我在Go(golang)中有一些代码,有几个不同的线程运行一个单独的可执行文件。我想确保如果用户在Go中杀死了我的进程,是否有一种方法可以杀死我调用的可执行文件,是否有办法做到这一点?

我不清楚您所说的“正在运行的不同线程”是什么意思。我会假设:

  • 那些线程属于“我所说的可执行文件”
  • 那些线程不一定用golang编写
  • 您无法控制它们的执行(即,您无法更改其代码)

从这个意义上讲,我们正在谈论创建一个进程组,并确保在终止进程时,该组中的所有其他进程也必须停止。此机制取决于操作系统。

在当前版本中,有两种可能性(请参见软件包x/sys):