|
|
@ -17,11 +17,8 @@ |
|
|
|
package main |
|
|
|
package main |
|
|
|
|
|
|
|
|
|
|
|
import ( |
|
|
|
import ( |
|
|
|
"errors" |
|
|
|
|
|
|
|
"fmt" |
|
|
|
"fmt" |
|
|
|
"net" |
|
|
|
"net" |
|
|
|
"os" |
|
|
|
|
|
|
|
"syscall" |
|
|
|
|
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
// Make sure that none of the other processes are listening on the
|
|
|
|
// Make sure that none of the other processes are listening on the
|
|
|
@ -32,69 +29,18 @@ import ( |
|
|
|
// However on Mac OSX Listen() on ":9000" falls back to the IPv6 address.
|
|
|
|
// 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
|
|
|
|
// 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
|
|
|
|
// 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 all the IPs.
|
|
|
|
// the minio server we make sure that the port is free on each tcp network.
|
|
|
|
func checkPortAvailability(port int) error { |
|
|
|
func checkPortAvailability(port int) error { |
|
|
|
isAddrInUse := func(err error) bool { |
|
|
|
network := [3]string{"tcp", "tcp4", "tcp6"} |
|
|
|
// Check if the syscall error is EADDRINUSE.
|
|
|
|
for _, n := range network { |
|
|
|
// EADDRINUSE is the system call error if another process is
|
|
|
|
l, err := net.Listen(n, fmt.Sprintf(":%d", port)) |
|
|
|
// already listening at the specified port.
|
|
|
|
|
|
|
|
neterr, ok := err.(*net.OpError) |
|
|
|
|
|
|
|
if !ok { |
|
|
|
|
|
|
|
return false |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
osErr, ok := neterr.Err.(*os.SyscallError) |
|
|
|
|
|
|
|
if !ok { |
|
|
|
|
|
|
|
return false |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
sysErr, ok := osErr.Err.(syscall.Errno) |
|
|
|
|
|
|
|
if !ok { |
|
|
|
|
|
|
|
return false |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if sysErr != syscall.EADDRINUSE { |
|
|
|
|
|
|
|
return false |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return true |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ifcs, err := net.Interfaces() |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
return err |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for _, ifc := range ifcs { |
|
|
|
|
|
|
|
addrs, err := ifc.Addrs() |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for _, addr := range addrs { |
|
|
|
// look for error so we don't have dangling connection
|
|
|
|
ipnet, ok := addr.(*net.IPNet) |
|
|
|
if err = l.Close(); err != nil { |
|
|
|
if !ok { |
|
|
|
return err |
|
|
|
errorIf(errors.New(""), "Failed to assert type on (*net.IPNet) interface.") |
|
|
|
|
|
|
|
continue |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ip := ipnet.IP |
|
|
|
|
|
|
|
network := "tcp4" |
|
|
|
|
|
|
|
if ip.To4() == nil { |
|
|
|
|
|
|
|
network = "tcp6" |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
l, err := net.Listen(network, fmt.Sprintf(":%d", port)) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
if isAddrInUse(err) { |
|
|
|
|
|
|
|
// Fail if port is already in use.
|
|
|
|
|
|
|
|
return err |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Ignore other errors.
|
|
|
|
|
|
|
|
continue |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if err = l.Close(); err != nil { |
|
|
|
|
|
|
|
return err |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|