ncsid: Fix interruptible RA
Capturing directly from a subshell into a variable blocks the bash
process from waiting on a signal. Instead, use `coproc` and `read` to
achieve the same result.
Change-Id: I7ad8b01e2508c5a0c871d77d3a629ac5812656c5
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/subprojects/ncsid/src/ncsid_lib.sh b/subprojects/ncsid/src/ncsid_lib.sh
index a8fca22..7c1803d 100644
--- a/subprojects/ncsid/src/ncsid_lib.sh
+++ b/subprojects/ncsid/src/ncsid_lib.sh
@@ -17,7 +17,7 @@
HandleTerm() {
GOT_TERM=1
if ShouldTerm && (( ${#CHILD_PIDS[@]} > 0 )); then
- kill "${!CHILD_PIDS[@]}"
+ kill -s TERM "${!CHILD_PIDS[@]}"
fi
}
@@ -93,6 +93,24 @@
fi
}
+# Runs the provided commandline to completion, capturing stdout
+# into a variable
+CaptureInterruptible() {
+ local var="$1"
+ shift
+ if ShouldTerm; then
+ return 143
+ fi
+ coproc "$@" || return
+ local child_pid="$COPROC_PID"
+ CHILD_PIDS["$child_pid"]=1
+ exec {COPROC[1]}>&-
+ read -d $'\0' -ru "${COPROC[0]}" "$var" || true
+ wait "$child_pid" || true
+ unset CHILD_PIDS[$child_pid]
+ wait "$child_pid"
+}
+
# Determines if an address could be a valid IPv4 address
# NOTE: this doesn't sanitize invalid IPv4 addresses
IsIPv4() {
@@ -441,7 +459,7 @@
else
args+=(-r "$retries")
fi
- output="$(RunInterruptible rdisc6 "${args[@]}")" || st=$?
+ CaptureInterruptible output rdisc6 "${args[@]}" || st=$?
if (( st != 0 )); then
echo "rdisc6 failed with: " >&2
echo "$output" >&2
diff --git a/subprojects/ncsid/src/update_ra_neighbor.sh b/subprojects/ncsid/src/update_ra_neighbor.sh
index 02b5908..1fb6b58 100644
--- a/subprojects/ncsid/src/update_ra_neighbor.sh
+++ b/subprojects/ncsid/src/update_ra_neighbor.sh
@@ -33,8 +33,10 @@
return 0
fi
+ local st=0
local disc
- if ! disc="$(DiscoverRouter6 "$netdev" -1 360000 "$DefaultGateway6")"; then
+ CaptureInterruptible disc DiscoverRouter6 "$netdev" -1 360000 "$DefaultGateway6" || st=$?
+ if (( st != 0 )); then
echo "Failed to discover router" >&2
return 1
fi