我有一些代码在Go(golang)中,有几个不同的线程运行一个单独的可执行文件。我想确保如果用户在Go中杀死我的进程,我有办法杀死我所称的可执行文件,有没有办法做到这一点?
答案 0 :(得分:5)
确保子进程被终止的唯一方法是在同一进程组中启动它,并将进程组作为一个整体终止,或者在syscall.SetProcAddr
中设置Pdeadthsig
。 / p>
您可以为SIG_INT
和SIG_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中杀死了我的进程,是否有一种方法可以杀死我调用的可执行文件,是否有办法做到这一点?
我不清楚您所说的“正在运行的不同线程”是什么意思。我会假设:
从这个意义上讲,我们正在谈论创建一个进程组,并确保在终止进程时,该组中的所有其他进程也必须停止。此机制取决于操作系统。
在当前版本中,有两种可能性(请参见软件包x/sys):
Unix :即将setgid(2)
Windows :即将CreateProcess
。请参考MS Windows documentation CreateProcess。您必须通过CREATE_NEW_PROCESS_GROUP
标志(see)