mirror of
https://github.com/vdsm/virtual-dsm.git
synced 2026-08-28 20:06:05 +00:00
feat: Preserve graceful shutdown for interactive console (#1289)
This commit is contained in:
+6
-3
@@ -32,14 +32,17 @@ if ! enabled "$SHUTDOWN"; then
|
||||
exec "${cmd[@]}" ${ARGS:+ $ARGS}
|
||||
fi
|
||||
|
||||
if [ ! -t 1 ] || [ ! -c /dev/tty ]; then
|
||||
if ! interactive; then
|
||||
"${cmd[@]}" ${ARGS:+ $ARGS} &
|
||||
else
|
||||
"${cmd[@]}" ${ARGS:+ $ARGS} </dev/tty >/dev/tty &
|
||||
startConsole
|
||||
setsid -w "${cmd[@]}" ${ARGS:+ $ARGS} </dev/null &
|
||||
fi
|
||||
|
||||
pid=$!
|
||||
rc=0
|
||||
wait $! || rc=$?
|
||||
|
||||
wait "$pid" || rc=$?
|
||||
[ -f "$QEMU_END" ] && exit "$rc"
|
||||
|
||||
sleep 1 & wait $!
|
||||
|
||||
+2
-2
@@ -1568,8 +1568,8 @@ closeInterfaces() {
|
||||
local pids=( "$PASST_PID" "$DNSMASQ_PID" )
|
||||
mKill "${pids[@]}"
|
||||
|
||||
exec 30>&- 2>/dev/null || true
|
||||
exec 40>&- 2>/dev/null || true
|
||||
exec 30<&- || :
|
||||
exec 40<&- || :
|
||||
|
||||
ip link set "$TAP" down promisc off &> /dev/null || :
|
||||
ip link delete "$TAP" &> /dev/null || :
|
||||
|
||||
+64
-7
@@ -10,14 +10,18 @@ set -Eeuo pipefail
|
||||
API_CMD=6
|
||||
API_HOST="127.0.0.1:$COM_PORT"
|
||||
|
||||
# Configure QEMU for graceful shutdown
|
||||
SHUTDOWN_SKIP=0
|
||||
SHUTDOWN_SIGNAL=0
|
||||
|
||||
QEMU_END="$QEMU_DIR/qemu.end"
|
||||
CONSOLE_PID="$QEMU_DIR/console.pid"
|
||||
CONSOLE_SOCKET="$QEMU_DIR/console.sock"
|
||||
|
||||
_trap() {
|
||||
|
||||
local func="$1"; shift
|
||||
local sig
|
||||
|
||||
TRAP_PID=$BASHPID
|
||||
|
||||
for sig; do
|
||||
@@ -88,7 +92,7 @@ forceKillQemu() {
|
||||
|
||||
cleanupHelpers() {
|
||||
|
||||
local pids=( "${HOST_PID:-}" "${WSD_PID:-}" \
|
||||
local pids=( "${HOST_PID:-}" "${WSD_PID:-}" "${CONSOLE_PID:-}" \
|
||||
"${WEB_PID:-}" "${PASST_PID:-}" "${DNSMASQ_PID:-}" )
|
||||
|
||||
mKill "${pids[@]}"
|
||||
@@ -98,6 +102,47 @@ cleanupHelpers() {
|
||||
return 0
|
||||
}
|
||||
|
||||
startConsole() {
|
||||
|
||||
local cnt=0
|
||||
local pid=""
|
||||
|
||||
rm -f -- "$CONSOLE_SOCKET" "$CONSOLE_PID"
|
||||
|
||||
if ! stty -icanon -echo isig -ixon min 1 time 0 </dev/tty; then
|
||||
error "Failed to configure serial console terminal!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
(
|
||||
trap '' INT QUIT
|
||||
exec nc -lU "$CONSOLE_SOCKET" </dev/tty >/dev/tty
|
||||
) &
|
||||
|
||||
pid=$!
|
||||
echo "$pid" > "$CONSOLE_PID"
|
||||
|
||||
while [ ! -S "$CONSOLE_SOCKET" ]; do
|
||||
|
||||
if ! isAlive "$pid"; then
|
||||
rm -f -- "$CONSOLE_PID"
|
||||
error "Serial console relay exited unexpectedly!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
sleep 0.02
|
||||
cnt=$((cnt + 1))
|
||||
|
||||
if (( cnt > 100 )); then
|
||||
error "Failed to start serial console relay!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
finish() {
|
||||
|
||||
local reason=$1
|
||||
@@ -198,7 +243,7 @@ waitForShutdown() {
|
||||
local name="$APP"
|
||||
local slp
|
||||
|
||||
while (( cnt <= wait_until )); do
|
||||
while (( cnt <= wait_until && SHUTDOWN_SKIP == 0 )); do
|
||||
|
||||
sleep 1 &
|
||||
slp=$!
|
||||
@@ -216,7 +261,7 @@ waitForShutdown() {
|
||||
info "Waiting for $name to shut down... ($cnt/$wait_until)"
|
||||
fi
|
||||
|
||||
wait "$slp"
|
||||
wait "$slp" || :
|
||||
(( cnt++ ))
|
||||
|
||||
done
|
||||
@@ -235,21 +280,29 @@ graceful_shutdown() {
|
||||
code=$(signalCode "$sig")
|
||||
|
||||
if [ -f "$QEMU_END" ]; then
|
||||
echo && info "Received $1 signal while already shutting down..."
|
||||
|
||||
if (( code == 130 && SHUTDOWN_SIGNAL == code )); then
|
||||
SHUTDOWN_SKIP=1
|
||||
echo && info "Received SIGINT again, forcing shutdown..." return
|
||||
fi
|
||||
|
||||
echo && info "Received $sig signal while already shutting down..."
|
||||
return
|
||||
fi
|
||||
|
||||
set +e
|
||||
start=$SECONDS
|
||||
SHUTDOWN_SIGNAL=$code
|
||||
|
||||
touch "$QEMU_END"
|
||||
echo && info "Received $1 signal, sending shutdown command..."
|
||||
echo && info "Received $sig signal, sending shutdown command..."
|
||||
|
||||
if ! readQemuPid pid; then
|
||||
warn "QEMU PID file ($QEMU_PID) does not exist?"
|
||||
finish "$code"
|
||||
fi
|
||||
|
||||
if ! isAlive "$pid"; then
|
||||
if [ -z "$pid" ] || ! isAlive "$pid"; then
|
||||
warn "QEMU process with PID $pid does not exist?"
|
||||
finish "$code"
|
||||
fi
|
||||
@@ -264,6 +317,10 @@ graceful_shutdown() {
|
||||
! enabled "$SHUTDOWN" && return 0
|
||||
[ -n "${QEMU_TIMEOUT:-}" ] && TIMEOUT="$QEMU_TIMEOUT"
|
||||
|
||||
if interactive; then
|
||||
_trap graceful_shutdown SIGINT
|
||||
fi
|
||||
|
||||
_trap graceful_shutdown SIGTERM SIGHUP SIGABRT SIGQUIT
|
||||
|
||||
return 0
|
||||
|
||||
+27
-13
@@ -52,27 +52,25 @@ buildHostArguments() {
|
||||
|
||||
startHostBinary() {
|
||||
|
||||
local pid=""
|
||||
local pid
|
||||
|
||||
if enabled "$HOST_DEBUG"; then
|
||||
|
||||
{
|
||||
set -x
|
||||
./host.bin "${HOST_ARGS[@]}" &
|
||||
pid=$!
|
||||
{ set +x; } 2>/dev/null
|
||||
} 2>&1
|
||||
|
||||
echo "$pid" > "$HOST_PID"
|
||||
set -x
|
||||
./host.bin "${HOST_ARGS[@]}" &
|
||||
{ set +x; } 2>/dev/null
|
||||
pid=$!
|
||||
echo
|
||||
else
|
||||
./host.bin "${HOST_ARGS[@]}" >/dev/null &
|
||||
echo "$!" > "$HOST_PID"
|
||||
pid=$!
|
||||
fi
|
||||
|
||||
echo "$pid" > "$HOST_PID"
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
waitForPort() {
|
||||
|
||||
local port="$1"
|
||||
@@ -90,13 +88,29 @@ waitForPort() {
|
||||
|
||||
configureSerialPorts() {
|
||||
|
||||
# Configure serial ports
|
||||
SERIAL_OPTS="-serial mon:stdio \
|
||||
if enabled "${SHUTDOWN:-Y}" && interactive; then
|
||||
|
||||
CONSOLE_SOCKET="$QEMU_DIR/console.sock"
|
||||
MONITOR_SOCKET="$QEMU_DIR/monitor.sock"
|
||||
|
||||
SERIAL_OPTS="-chardev socket,id=console0,path=$CONSOLE_SOCKET,reconnect-ms=1000 \
|
||||
-serial chardev:console0 \
|
||||
-chardev socket,id=monitor0,path=$MONITOR_SOCKET,server=on,wait=off \
|
||||
-mon chardev=monitor0,mode=readline"
|
||||
|
||||
else
|
||||
|
||||
SERIAL_OPTS="-serial mon:stdio"
|
||||
|
||||
fi
|
||||
|
||||
SERIAL_OPTS+=" \
|
||||
-device virtio-serial-pci,id=virtio-serial0,bus=pcie.0,addr=0x3 \
|
||||
-chardev socket,id=charchannel0,host=127.0.0.1,port=$CHR_PORT,reconnect=10 \
|
||||
-device virtserialport,bus=virtio-serial0.0,nr=1,chardev=charchannel0,id=channel0,name=vchannel"
|
||||
|
||||
return 0
|
||||
|
||||
}
|
||||
|
||||
validateHostMac
|
||||
|
||||
@@ -7,6 +7,14 @@ info () { printf "%b%s%b" "\E[1;34m❯ \E[1;36m" "${1:-}" "\E[0m\n"; }
|
||||
error () { printf "%b%s%b" "\E[1;31m❯ " "ERROR: ${1:-}" "\E[0m\n" >&2; }
|
||||
warn () { printf "%b%s%b" "\E[1;31m❯ " "Warning: ${1:-}" "\E[0m\n" >&2; }
|
||||
|
||||
interactive() {
|
||||
|
||||
[ -t 1 ] &&
|
||||
[ -c /dev/tty ] &&
|
||||
: 2>/dev/null </dev/tty >/dev/tty
|
||||
|
||||
}
|
||||
|
||||
strip() {
|
||||
|
||||
local value="${1:-}"
|
||||
|
||||
Reference in New Issue
Block a user