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

时间:2013-06-19 13:52:14

标签: go file-descriptor

我几个小时都被困在这个问题上:

我有一个主进程作为TCP服务器,主进程调用Fork(),将其net.Listener()的FD传递给子进程。然后子进程可以使用net.Filelistener()继承此FD。

我通过许多开源代码研究了这个问题,也进行了一些实验。但遗憾的是,由于这些解决方案不便携,所以这些解决方案都不能满足我的要求,还需要许多危险的低级别工作。

如果有任何解决办法将net.Listener()的FD安全地传递给子进程,我很高兴知道。

我现在尝试过:

  1. 环境值,不便携,会导致许多FD混乱,不安全,因为可以从外面更改。

  2. Dup FD&清除FD_CLOEXEC然后exec / fork,可移植但不受Go API支持,提交给开发团队的syscall.NoCloseOnExec()更改被拒绝,因为他们希望保持系统调用干净。

  3. 设置SO_REUSEADDR以便子进程可以立即侦听端口,在此之前关闭父进程的侦听器。 Go API不支持失败,不可移植,也不安全。

  4. exec.Command.ExtraFiles(),不知道如何从子进程获取继承的FD,我是否需要配置文件来保存FD&名字呢?这个解决方案也有一个bug,请阅读exec的文档以获取更多细节。

  5. 好的家伙,我写了一个关于这个问题的简单测试案例(解决方案4):

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

    OS X上还包括2个可执行文件。 Linux操作系统。我试过Go 1.1&转到1.1.1,但这个问题仍然存在。

2 个答案:

答案 0 :(得分:4)

最简单的方法是在exec.Cmd的ExtraFiles字段中传递侦听器。

父母的例子:

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

孩子的例子:

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

您可能还想对此进行概括,并让孩子接受PROGRAMNAME_LISTENER_FD作为环境变量。然后,父级会在启动子级之前将环境变量设置为3。

答案 1 :(得分:0)

我正在寻找用于侦听回送地址和读取数据并发送到WINDOWS中的exec命令的

任何建议,因为Windows不支持文件描述符 在UNIX中,我们按照以下步骤进行操作

service:=“:1200”     tcpAddr,err:= net.ResolveTCPAddr(“ tcp”,服务)

erf(x) = 2/sqrt(pi) * integral(@(t)exp(-t.^2),0,x)

cmd:= exec.Command(execname)

cmd.ExtraFiles = [] * os.File {file}->在Unix中,它支持/如何在Windows中添加数据?

cmd.Start()