fix: do port availability check only on macOS. (#3654)

On macOS, if a process already listens on 127.0.0.1:PORT, net.Listen() falls back
to IPv6 address ie minio will start listening on IPv6 address whereas another
(non-)minio process is listening on IPv4 of given port.
To avoid this error sutiation we check for port availability only for macOS.

Note: checkPortAvailability() tries to listen on given port and closes it.
It is possible to have a disconnected client in this tiny window of time.
This commit is contained in:
Bala FA 2017-01-30 14:14:36 +05:30 committed by Harshavardhana
parent b408d0e87d
commit cc1575f944
2 changed files with 13 additions and 20 deletions

View File

@ -22,25 +22,13 @@ import (
"syscall" "syscall"
) )
// Make sure that none of the other processes are listening on the // checkPortAvailability - check if given port is already in use.
// specified port on any of the interfaces. // Note: The check method tries to listen on given port and closes it.
// // It is possible to have a disconnected client in this tiny window of time.
// On linux if a process is listening on 127.0.0.1:9000 then Listen() func checkPortAvailability(port string) error {
// on ":9000" fails with the error "port already in use".
// However on Mac OSX Listen() on ":9000" falls back to the IPv6 address.
// This causes confusion on Mac OSX that minio server is not reachable
// on 127.0.0.1 even though minio server is running. So before we start
// the minio server we make sure that the port is free on each tcp network.
//
// Port is string on purpose here.
// https://github.com/golang/go/issues/16142#issuecomment-245912773
//
// "Keep in mind that ports in Go are strings: https://play.golang.org/p/zk2WEri_E9"
// - @bradfitz
func checkPortAvailability(portStr string) error {
network := [3]string{"tcp", "tcp4", "tcp6"} network := [3]string{"tcp", "tcp4", "tcp6"}
for _, n := range network { for _, n := range network {
l, err := net.Listen(n, net.JoinHostPort("", portStr)) l, err := net.Listen(n, net.JoinHostPort("", port))
if err != nil { if err != nil {
if isAddrInUse(err) { if isAddrInUse(err) {
// Return error if another process is listening on the // Return error if another process is listening on the

View File

@ -352,9 +352,14 @@ func getHostPort(address string) (host, port string, err error) {
return "", "", err return "", "", err
} }
// Check if port is available. if runtime.GOOS == "darwin" {
if err = checkPortAvailability(port); err != nil { // On macOS, if a process already listens on 127.0.0.1:PORT, net.Listen() falls back
return "", "", err // to IPv6 address ie minio will start listening on IPv6 address whereas another
// (non-)minio process is listening on IPv4 of given port.
// To avoid this error sutiation we check for port availability only for macOS.
if err = checkPortAvailability(port); err != nil {
return "", "", err
}
} }
// Success. // Success.