Refactoring checkPortAvailability to check each tcp network (tcp, tcp4, tcp6) if a port is taken. (#2325)

master
Jesse Lucas 8 years ago committed by Harshavardhana
parent 851d05161a
commit 4b05b6a6c1
  1. 68
      checkport.go

@ -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
}
} }
} }

Loading…
Cancel
Save