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