@@ -12,6 +12,7 @@ import (
1212 "strconv"
1313 "strings"
1414 "sync"
15+ "syscall"
1516 "time"
1617 "unicode"
1718
@@ -377,6 +378,17 @@ const (
377378 comprBufferSize = 64 * 1024 // 64 Kb
378379)
379380
381+ /*
382+ Checks if this error indicates that a chosen source port/address cannot be bound.
383+
384+ This is caused by one of the following:
385+ - The source address is already used by another socket,
386+ - The source address is reserved and the process does not have sufficient privileges to use it.
387+ */
388+ func isAddrUnavailableForUseErr (err error ) bool {
389+ return errors .Is (err , syscall .EADDRINUSE ) || errors .Is (err , syscall .EPERM )
390+ }
391+
380392// OpenShardConn opens connection mapped to a specific shard on Scylla node.
381393func OpenShardConn (ctx context.Context , addr string , si ShardInfo , cfg ConnConfig ) (* Conn , error ) {
382394 it := ShardPortIterator (si )
@@ -385,12 +397,16 @@ func OpenShardConn(ctx context.Context, addr string, si ShardInfo, cfg ConnConfi
385397 conn , err := OpenLocalPortConn (ctx , addr , it (), cfg )
386398 if err != nil {
387399 cfg .Logger .Infof ("%s dial error: %s (try %d/%d)" , addr , err , i , maxTries )
388- continue
400+ if isAddrUnavailableForUseErr (err ) {
401+ continue
402+ }
403+
404+ return nil , fmt .Errorf ("failed to open connection to shard: %w" , err )
389405 }
390406 return conn , nil
391407 }
392408
393- return nil , fmt .Errorf ("failed to open connection on shard %d: all local ports are busy " , si .Shard )
409+ return nil , fmt .Errorf ("failed to open connection on shard %d: all local ports are unavailable for use " , si .Shard )
394410}
395411
396412// OpenLocalPortConn opens connection on a given local port.
0 commit comments