dongluzhi5208
2013-06-19 13:52 阅读 61
已采纳

如何安全地将net.Listener()的FD传递给子进程?

I've been stucked with this issue for hours:

I have a main process served as a TCP server, the main process call Fork(), pass its net.Listener()'s FD to child process. Then child process can use net.Filelistener() to inherit this FD.

I have researched this issue through many open-sourced codes, also did some experiments. But unfortunately none of these solutions satisfy me for now since they are not portable, you also need many low-level jobs which are dangerous.

If there's any solution to pass net.Listener()'s FD to child process SAFELY, I'd be glad to know.

What I've tried for now:

  1. Environment values, not portable, will cause chaos with many FDs, not safe since can be changed from outside.

  2. Dup FD & Clear FD_CLOEXEC then exec/fork, portable but not supported by Go API, a syscall.NoCloseOnExec() change submitted to dev team was rejected since they want to keep syscall clean.

  3. Set SO_REUSEADDR so child process can listen to port instantly, close parent's listener before that. Failed, not portable, not supported by Go API, also unsafe.

  4. exec.Command.ExtraFiles(), have no idea how to get inherited FDs from child process, do I need a config file to save FD & names? This solution also have a bug, read exec's document for more detail.

All right guys, I've written a simple test case of this issue(with solution 4):

https://github.com/reckhou/go-fd-pass-test

Also include 2 executables on OS X & Linux. I tried Go 1.1 & Go 1.1.1 but this issue still remains.

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

2条回答 默认 最新

  • 已采纳
    dora12345678 dora12345678 2013-06-19 18:00

    The easiest way is to pass the listener in the ExtraFiles field of exec.Cmd.

    Example of parent:

    var l *net.TCPListener
    cmd := exec.Command(...)
    f, err := l.File()
    cmd.ExtraFiles = []*os.File{f}
    

    Example of child:

    l, err := net.FileListener(os.NewFile(3, "listener"))
    

    You may also want to generalize this and have the child accept PROGRAMNAME_LISTENER_FD as an environment variable. Then the parent would set the environment variable to 3 before starting the child.

    点赞 评论 复制链接分享
  • dongtao4787 dongtao4787 2018-12-08 23:18

    I am looking for same to listen loopback adresss and read data and send to exec command in WINDOWS .

    Any suggestion as windows don’t support File descriptars IN UNIX WE DO AS FOLLOWS

    service := ":1200" tcpAddr, err := net.ResolveTCPAddr("tcp", service)

    listener, err := net.ListenTCP("tcp",tcpAddr)
    if err != nil {
        return "", err
    }
    
    defer listener.Close()
    file, err := listener.File()   --> unix supports file descriptor / how about in windows ??
    if err != nil {  
        return "", err
    }
    

    cmd := exec.Command( execname)

    cmd.ExtraFiles = []*os.File{file} --> in unix it support / how about in windows to add data ???

    cmd.Start()

    点赞 评论 复制链接分享

相关推荐