diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh index 9a89689ede6..f9e563c2a95 100644 --- a/scripts/wsrep_sst_common.sh +++ b/scripts/wsrep_sst_common.sh @@ -1233,6 +1233,7 @@ check_sockets_utils() # sockstat in FreeBSD is different from other systems, # let's denote it with a different value: sockstat_available=2 + sockstat_opts='-46lq -P tcp -p' fi else socket_utility="$(commandex lsof)" @@ -1277,18 +1278,25 @@ check_port() [ $pid -le 0 ] && pid='[0-9]+' - local rc=1 + local rc=2 # ENOENT if [ $ss_available -ne 0 ]; then $socket_utility $ss_opts -t "( sport = :$port )" 2>/dev/null | \ grep -q -E "[[:space:]]users:[[:space:]]?\\(.*\\(\"($utils)[^[:space:]]*\"[^)]*,pid=$pid(,[^)]*)?\\)" && rc=0 elif [ $sockstat_available -ne 0 ]; then if [ $sockstat_available -gt 1 ]; then - # sockstat on FreeBSD does not return the connection - # state without special option that cancel filtering - # by the port, so we ignore the connection state for - # this system: - $socket_utility $sockstat_opts "$port" 2>/dev/null | \ + # The sockstat command on FreeBSD does not return + # the connection state without special option, but + # it supports filtering by connection state: + local out + out=$($socket_utility $sockstat_opts "$port" 2>/dev/null) || rc=16 # EBUSY + # On FreeBSD, the sockstat utility may exit without + # any output due to locking issues in certain versions; + # let's return a special exit code in such cases: + if [ $rc -eq 16 -o -z "$out" ]; then + return 16 # EBUSY + fi + echo "$out" | \ grep -q -E "^[^[:space:]]+[[:space:]]+($utils)[^[:space:]]*[[:space:]]+$pid([[:space:]]|\$)" && rc=0 else $socket_utility $sockstat_opts "$port" 2>/dev/null | \ diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index 8acca6f1171..eb68d134eff 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -112,11 +112,11 @@ check_pid_and_port() grep -o -E "([^[:space:]]+[[:space:]]+){4}[^[:space:]]+" || :) else if [ $sockstat_available -gt 1 ]; then - # sockstat on FreeBSD does not return the connection - # state without special option that cancel filtering - # by the port, so we ignore the connection state for - # this system, also on the FreeBSD sockstat utility - # produces an additional column: + # The sockstat command on FreeBSD does not return + # the connection state without special option, but + # it supports filtering by connection state. + # Additionally, the sockstat utility on FreeBSD + # produces an one extra column: port_info=$($socket_utility $sockstat_opts "$port" 2>/dev/null | \ grep -o -E "([^[:space:]]+[[:space:]]+){5}[^[:space:]]+" || :) else @@ -149,7 +149,14 @@ check_pid_and_port() return 1 fi - if ! check_port $pid "$port" "$utils"; then + local rc=0 + check_port $pid "$port" "$utils" || rc=$? + if [ $rc -eq 16 ]; then + # We will ignore the return code EBUSY, which indicates + # a failed attempt to run the utility for retrieving + # socket information (on some systems): + return 1 + elif [ $rc -ne 0 ]; then wsrep_log_error "rsync or stunnel daemon port '$port'" \ "has been taken by another program" exit 16 # EBUSY