2017-02-28 23 views
0

在執行的過程和使用發送信號到它的過程已經結束如預期。OS:發送syscall.SIGCONT時(?可能的錯誤)

爲了便於說明我已經創建了這個簡單的例子:

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上的錯誤還是它的預期行爲?

UPDATE:似乎只在Mac OS X是發生

+0

您在命令結構上存在爭用條件。您需要首先解決這個問題,然後才能定義此程序的行爲。 – JimB

+0

@JimB,你好,請你幫我理解競賽狀況或如何測試它?提前致謝。 – nbari

+0

比賽很簡單,運行比賽探測器,它會告訴你它到底在哪裏。我想通了,但是,即使設置了WEXITED,達爾文似乎從SIGSTOP的第一個wait4返回,標誌着過程完成並阻止進一步的信號。它只會在調用併發等待時纔會發生。我不確定Go是否能解決這個問題,達爾文內核不合作。 – JimB

回答

0

issue似乎只發生在Mac OS X,在 「內華達」 和 「酋長」 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() 
}