Go 如何传递net.Listener();FD到子进程安全吗?
这个问题困扰了我好几个小时: 我有一个主进程作为TCP服务器,主进程调用Fork(),将其net.Listener()的FD传递给子进程。然后子进程可以使用net.Filelistener()继承此FD 我通过许多开源代码研究了这个问题,也做了一些实验。但不幸的是,这些解决方案目前都不能让我满意,因为它们不可移植,你还需要很多危险的低级工作 如果有任何解决方案可以安全地将net.Listener()的FD传递给子进程,我很乐意知道 我现在尝试的是:Go 如何传递net.Listener();FD到子进程安全吗?,go,file-descriptor,Go,File Descriptor,这个问题困扰了我好几个小时: 我有一个主进程作为TCP服务器,主进程调用Fork(),将其net.Listener()的FD传递给子进程。然后子进程可以使用net.Filelistener()继承此FD 我通过许多开源代码研究了这个问题,也做了一些实验。但不幸的是,这些解决方案目前都不能让我满意,因为它们不可移植,你还需要很多危险的低级工作 如果有任何解决方案可以安全地将net.Listener()的FD传递给子进程,我很乐意知道 我现在尝试的是: 环境值不可移植,将导致许多FD混乱,因为可以从
FD_CLOEXEC
then exec/fork,可移植但不受Go API支持,提交给开发团队的syscall.NoCloseOnExec()
更改被拒绝,因为他们希望保持系统调用干净SO\u REUSEADDR
以便子进程可以立即侦听端口,在此之前关闭父进程的侦听器。失败,不可移植,Go API不支持,也不安全exec.Command.ExtraFiles()
,不知道如何从子进程获取继承的FD,是否需要配置文件来保存FD&name?此解决方案还有一个bug,请阅读exec的文档以了解更多详细信息在OS X和Linux上还包括2个可执行文件。我尝试了Go 1.1和Go 1.1.1,但这个问题仍然存在。最简单的方法是在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\u LISTENER\u FD作为环境变量。然后,父级将在启动子级之前将环境变量设置为3。我正在寻找相同的环境变量,以便在WINDOWS中侦听环回地址、读取数据并发送到exec命令 任何建议,因为windows不支持文件描述符 在UNIX中,我们执行以下操作 服务:=“:1200” tcpAddr,err:=net.ResolveTCPAddr(“tcp”,服务) cmd:=exec.Command(execname) cmd.ExtraFiles=[]*os.File{File}-->在unix it支持中/在windows中如何添加数据
cmd.Start()您介意发布一些代码吗?特别是你想要避免的不安全的东西?这将有助于回答您的问题。我将稍后发布我的解决方案,但不是现在,因为它可能会设置限制。我认为
[]*os.File{l}
应该是[]*os.File{f}
。使用环境变量不是一个好主意,因为可能正在运行多个FD。稍后我将测试此解决方案。另一个问题是如何从子进程继承FD?您没有显示3,“侦听器”
是如何出现的。事实上,这一部分对于可扩展服务非常重要。此解决方案还有一个bug:请阅读上面的注释ExtraFiles[]*os.File
。我已经测试了此代码,发现它在os X和centOS上都不起作用。对此很抱歉,但目前看来只有FD_CLOEXEC在工作。我在golang.org上看到没有实现TCPListen和TCConn,在Windows中有任何建议吗
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
}