doulaozhang0238
2014-08-02 12:19
浏览 123
已采纳

如何在Windows的golang中验证父进程已退出?

So I am writing a small utility which should be able to update itself (replace it's own binary).

The best way to do this on Windows seems to be:

  1. Download the new version of the binary as my.exe.new
  2. my.exes runs my.exe.new and exits
  3. my.exe.new waits for my.exe to exit
  4. my.exe.new copies itself as my.exe
  5. my.exe.new starts another copy of itself as my.exe and exits
  6. my.exe waits for my.exe.new to exit
  7. my.exe removes my.exe.new

Now for all of this to work I have to be able to synchronize the state between the processes (being able to know when the parent has exited), but it seems that os.Getppid (nor syscall.Getppid) in golang Windows is not implemented as it always returns -1.

I've seen that patches are underway, but I am not willing to patch my standard libraries.

Is there an easy way to make Getppid working on even older versions of Go (perhaps reimplementing it?), or perhaps anyone can suggest a better method of synchronizing between the process state?

The thing which comes to mind is binding on a socket, but thats a big hacky.

Perhaps passing a pipe to the child process, and the child waiting for the pipe to close?

Thanks

图片转代码服务由CSDN问答提供 功能建议

因此,我正在编写一个小型实用程序,该实用程序应该能够自我更新(替换为自己的二进制文件)。

在Windows上执行此操作的最佳方法似乎是:

  1. 将二进制文件的新版本下载为my.exe。 .new
  2. my.exes运行my.exe.new并退出
  3. my.exe.new等待my.exe退出 < li> my.exe.new将自身复制为my.exe
  4. my.exe.new将其自身的另一个副本复制为my.exe并退出
  5. my.exe 等待my.exe.new退出
  6. my.exe删除my.exe.new

    现在所有这些操作 工作,我必须能够同步进程之间的状态(能够知道父进程何时退出),但是在golang Windows中似乎未实现os.Getppid(也没有syscall.Getppid),因为它总是返回-1

    我已经看到修补程序正在进行中,但是我不愿意修补我的标准库。

    有一种简单的制作方法 Getppid甚至可以在旧版本的Go上工作(也许重新实现它?),或者也许有人可以建议一种更好的在进程状态之间进行同步的方法?

    我想到的是绑定到套接字上,但这是一个很大的漏洞。

    也许将管道传递给子进程,而子进程正在等待管道 关闭?

    谢谢

  • 写回答
  • 好问题 提建议
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • doulin2947 2014-08-02 23:54
    已采纳

    The parent process can pass its PID to the child.

    You could use a command-line parameter or an environment variable to do this.

    已采纳该答案
    评论
    解决 无用
    打赏 举报
  • doukang2003 2014-08-02 17:36

    You could use os.Stdin with exec.Cmd, now I don't have access to windows to test this, however the same concept should apply there just fine:

    var child = flag.Bool("child", false, "damn children and their music")
    
    func init() {
        flag.Parse()
    }
    
    func main() {
        if *child {
            fmt.Println("child start", time.Now())
    
            // wait until the parent dies and bufio closes the stdin
            ioutil.ReadAll(os.Stdin)
            fmt.Println("the parent is dead", time.Now())
            time.Sleep(5 * time.Second)
            fmt.Println("tada
    ")
    
        } else {
            fmt.Fprintln(os.Stdout, time.Now())
            cmd := exec.Command(os.Args[0], "-child")
            cmd.Stdout = os.Stdout //not needed in a real program.
    
            //this is important, bufio will close after the parent exits, 
            // unlike os.Stdin which screws up, at least on linux
            cmd.Stdin = bufio.NewReader(os.Stdin) 
    
            fmt.Println("giving painful birth:", cmd.Start())
            time.Sleep(2 * time.Second)
        }
    }
    
    评论
    解决 无用
    打赏 举报

相关推荐 更多相似问题