问题
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:
Environment values, not portable, will cause chaos with many FDs, not safe since can be changed from outside.
Dup FD & Clear
FD_CLOEXEC
then exec/fork, portable but not supported by Go API, asyscall.NoCloseOnExec()
change submitted to dev team was rejected since they want to keep syscall clean.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.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.
回答1:
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.
回答2:
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()
来源:https://stackoverflow.com/questions/17193086/how-to-pass-net-listeners-fd-to-child-process-safely