os:发送 syscall.SIGCONT 时进程已经完成(possible bug?)
os: process already finished when sending syscall.SIGCONT (possible bug?)
当执行进程并使用以下方式向其发送信号时:Process.Signal I notice that after sending the second signal syscall.SIGCONT
I got a: os: process already finished
but if using syscall.Kill一切正常。
为了演示 purposes 我创建了这个天真的例子:
package main
import (
"fmt"
"os"
"os/exec"
"syscall"
"time"
)
func main() {
exit := make(chan error, 1)
go run(exit)
for {
select {
case <-exit:
println("fin, restarting")
run(exit)
default:
time.Sleep(time.Second)
println("running...")
}
}
}
func run(ch chan<- error) {
cmd := exec.Command("sleep", "3")
if err := cmd.Start(); err != nil {
print(err.Error())
os.Exit(1)
}
fmt.Printf("Pid: %d\n", cmd.Process.Pid)
go func() {
ch <- cmd.Wait()
}()
time.Sleep(2 * time.Second)
fmt.Printf("%v\n", cmd.Process.Signal(syscall.SIGSTOP))
time.Sleep(2 * time.Second)
// Using this will return an os: process already finished
fmt.Printf("%v\n", cmd.Process.Signal(syscall.SIGCONT))
// This works as expected
//fmt.Printf("%v\n", syscall.Kill(cmd.Process.Pid, syscall.SIGCONT))
}
所以基本上如果使用:
cmd.Process.Signal(syscall.SIGCONT)
os: process already finished
返回
但是使用时:
syscall.Kill(cmd.Process.Pid, syscall.SIGCONT)
它按预期工作。
这可能是 os.exec 上的错误还是预期的行为?
更新:似乎只发生在 mac os X
这个issue seems to be only happening on Mac OS X, tested on "Sierra" and "El Capitan" https://go-review.googlesource.com/#/c/37610/
所以,就目前而言,为了更好地保持跨平台,用户:
syscall.Kill(cmd.Process.Pid, syscall.SIGCONT))
用于测试您的系统是否存在此问题的示例代码:
package main
import (
"fmt"
"log"
"os/exec"
"syscall"
"unsafe"
)
func main() {
cmd := exec.Command("sleep", "10")
if err := cmd.Start(); err != nil {
log.Fatal(err)
}
// signal when wait4 will return immediately
go func() {
var siginfo [128]byte
psig := &siginfo[0]
_, _, e := syscall.Syscall6(syscall.SYS_WAITID, 1, uintptr(cmd.Process.Pid), uintptr(unsafe.Pointer(psig)), syscall.WEXITED|syscall.WNOWAIT, 0, 0)
fmt.Println("WAITID RETURNED -- this shouldn't happen:", e)
}()
err := cmd.Process.Signal(syscall.SIGSTOP)
if err != nil {
log.Fatal(err)
}
cmd.Wait()
}
当执行进程并使用以下方式向其发送信号时:Process.Signal I notice that after sending the second signal syscall.SIGCONT
I got a: os: process already finished
but if using syscall.Kill一切正常。
为了演示 purposes 我创建了这个天真的例子:
package main
import (
"fmt"
"os"
"os/exec"
"syscall"
"time"
)
func main() {
exit := make(chan error, 1)
go run(exit)
for {
select {
case <-exit:
println("fin, restarting")
run(exit)
default:
time.Sleep(time.Second)
println("running...")
}
}
}
func run(ch chan<- error) {
cmd := exec.Command("sleep", "3")
if err := cmd.Start(); err != nil {
print(err.Error())
os.Exit(1)
}
fmt.Printf("Pid: %d\n", cmd.Process.Pid)
go func() {
ch <- cmd.Wait()
}()
time.Sleep(2 * time.Second)
fmt.Printf("%v\n", cmd.Process.Signal(syscall.SIGSTOP))
time.Sleep(2 * time.Second)
// Using this will return an os: process already finished
fmt.Printf("%v\n", cmd.Process.Signal(syscall.SIGCONT))
// This works as expected
//fmt.Printf("%v\n", syscall.Kill(cmd.Process.Pid, syscall.SIGCONT))
}
所以基本上如果使用:
cmd.Process.Signal(syscall.SIGCONT)
os: process already finished
返回
但是使用时:
syscall.Kill(cmd.Process.Pid, syscall.SIGCONT)
它按预期工作。
这可能是 os.exec 上的错误还是预期的行为?
更新:似乎只发生在 mac os X
这个issue seems to be only happening on Mac OS X, tested on "Sierra" and "El Capitan" https://go-review.googlesource.com/#/c/37610/
所以,就目前而言,为了更好地保持跨平台,用户:
syscall.Kill(cmd.Process.Pid, syscall.SIGCONT))
用于测试您的系统是否存在此问题的示例代码:
package main
import (
"fmt"
"log"
"os/exec"
"syscall"
"unsafe"
)
func main() {
cmd := exec.Command("sleep", "10")
if err := cmd.Start(); err != nil {
log.Fatal(err)
}
// signal when wait4 will return immediately
go func() {
var siginfo [128]byte
psig := &siginfo[0]
_, _, e := syscall.Syscall6(syscall.SYS_WAITID, 1, uintptr(cmd.Process.Pid), uintptr(unsafe.Pointer(psig)), syscall.WEXITED|syscall.WNOWAIT, 0, 0)
fmt.Println("WAITID RETURNED -- this shouldn't happen:", e)
}()
err := cmd.Process.Signal(syscall.SIGSTOP)
if err != nil {
log.Fatal(err)
}
cmd.Wait()
}