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, a syscall.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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With