From cc1575f9444334a0d145dd85a003604bde058b3c Mon Sep 17 00:00:00 2001 From: Bala FA Date: Mon, 30 Jan 2017 14:14:36 +0530 Subject: [PATCH] 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. --- cmd/checkport.go | 22 +++++----------------- cmd/server-main.go | 11 ++++++++--- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/cmd/checkport.go b/cmd/checkport.go index 489adfba3..648868520 100644 --- a/cmd/checkport.go +++ b/cmd/checkport.go @@ -22,25 +22,13 @@ import ( "syscall" ) -// Make sure that none of the other processes are listening on the -// specified port on any of the interfaces. -// -// On linux if a process is listening on 127.0.0.1:9000 then Listen() -// 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 { +// checkPortAvailability - check if given port is already in use. +// 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. +func checkPortAvailability(port string) error { network := [3]string{"tcp", "tcp4", "tcp6"} for _, n := range network { - l, err := net.Listen(n, net.JoinHostPort("", portStr)) + l, err := net.Listen(n, net.JoinHostPort("", port)) if err != nil { if isAddrInUse(err) { // Return error if another process is listening on the diff --git a/cmd/server-main.go b/cmd/server-main.go index 431d25a14..1971ef442 100644 --- a/cmd/server-main.go +++ b/cmd/server-main.go @@ -352,9 +352,14 @@ func getHostPort(address string) (host, port string, err error) { return "", "", err } - // Check if port is available. - if err = checkPortAvailability(port); err != nil { - return "", "", err + if runtime.GOOS == "darwin" { + // 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. + if err = checkPortAvailability(port); err != nil { + return "", "", err + } } // Success.