mirror of
https://github.com/dockur/windows.git
synced 2026-08-03 20:47:12 +01:00
feat: Use QEMU helpers from base image (#1914)
This commit is contained in:
+8
-283
@@ -15,112 +15,6 @@ CONSOLE_PID="$QEMU_DIR/console.pid"
|
|||||||
CONSOLE_SOCKET="$QEMU_DIR/console.sock"
|
CONSOLE_SOCKET="$QEMU_DIR/console.sock"
|
||||||
QEMU_START_PID="$QEMU_DIR/qemu.start.pid"
|
QEMU_START_PID="$QEMU_DIR/qemu.start.pid"
|
||||||
|
|
||||||
_trap() {
|
|
||||||
|
|
||||||
local func="$1"; shift
|
|
||||||
local sig
|
|
||||||
|
|
||||||
TRAP_PID=$BASHPID
|
|
||||||
|
|
||||||
for sig; do
|
|
||||||
# Capture the local callback and signal while registering the trap.
|
|
||||||
# shellcheck disable=SC2064
|
|
||||||
trap "$func $sig" "$sig"
|
|
||||||
done
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
signalCode() {
|
|
||||||
|
|
||||||
local sig="$1"
|
|
||||||
|
|
||||||
case "$sig" in
|
|
||||||
SIGHUP) echo 129 ;;
|
|
||||||
SIGINT) echo 130 ;;
|
|
||||||
SIGQUIT) echo 131 ;;
|
|
||||||
SIGABRT) echo 134 ;;
|
|
||||||
SIGTERM) echo 143 ;;
|
|
||||||
*) echo 0 ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
displayReason() {
|
|
||||||
|
|
||||||
local reason="$1"
|
|
||||||
|
|
||||||
case "$reason" in
|
|
||||||
129 ) echo "SIGHUP" ;;
|
|
||||||
130 ) echo "SIGINT" ;;
|
|
||||||
131 ) echo "SIGQUIT" ;;
|
|
||||||
134 ) echo "SIGABRT" ;;
|
|
||||||
143 ) echo "SIGTERM" ;;
|
|
||||||
* ) echo "$reason" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
readQemuPid() {
|
|
||||||
|
|
||||||
local -n _pid="$1"
|
|
||||||
local file
|
|
||||||
|
|
||||||
for file in "$QEMU_START_PID" "$QEMU_PID"; do
|
|
||||||
if [ -s "$file" ] && read -r _pid < "$file"; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
qemuPidFile() {
|
|
||||||
|
|
||||||
local -n _file="$1"
|
|
||||||
|
|
||||||
_file="$QEMU_PID"
|
|
||||||
[ -s "$QEMU_START_PID" ] && _file="$QEMU_START_PID"
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
terminateQemu() {
|
|
||||||
|
|
||||||
local file=""
|
|
||||||
|
|
||||||
qemuPidFile file
|
|
||||||
sKill "$file"
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
waitQemuExit() {
|
|
||||||
|
|
||||||
local timeout="${1:-10}"
|
|
||||||
local file=""
|
|
||||||
|
|
||||||
qemuPidFile file
|
|
||||||
waitPidFile "$file" "$timeout"
|
|
||||||
}
|
|
||||||
|
|
||||||
waitQemuPid() {
|
|
||||||
|
|
||||||
local -n _pid="$1"
|
|
||||||
local cnt=0 value=""
|
|
||||||
|
|
||||||
while ! readQemuPid value; do
|
|
||||||
sleep 0.02
|
|
||||||
cnt=$((cnt + 1))
|
|
||||||
(( cnt >= 50 )) && return 1
|
|
||||||
done
|
|
||||||
|
|
||||||
_pid="$value"
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
bootFailed() {
|
bootFailed() {
|
||||||
|
|
||||||
local fail=""
|
local fail=""
|
||||||
@@ -181,21 +75,6 @@ ready() {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
forceKillQemu() {
|
|
||||||
|
|
||||||
local reason="$1"
|
|
||||||
local pid="" display
|
|
||||||
|
|
||||||
! readQemuPid pid && return 0
|
|
||||||
! isAlive "$pid" && return 0
|
|
||||||
|
|
||||||
display=$(displayReason "$reason")
|
|
||||||
error "Forcefully terminating $(app), reason: $display..."
|
|
||||||
{ disown "$pid" || :; kill -9 -- "$pid" || :; } 2>/dev/null
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
markWindowsBooted() {
|
markWindowsBooted() {
|
||||||
|
|
||||||
local file="$STORAGE/windows.boot"
|
local file="$STORAGE/windows.boot"
|
||||||
@@ -225,92 +104,6 @@ markWindowsBooted() {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanupHelpers() {
|
|
||||||
|
|
||||||
local pids=( "${SMB_PID:-}" "${NMB_PID:-}" "${DDN_PID:-}" \
|
|
||||||
"${TPM_PID:-}" "${WSD_PID:-}" "${WEB_PID:-}" \
|
|
||||||
"${AUX_PID:-}" "${AUDIO_PID:-}" "${CONSOLE_PID:-}" \
|
|
||||||
"${PASST_PID:-}" "${DNSMASQ_PID:-}" "${BALLOONING_PID:-}" )
|
|
||||||
|
|
||||||
mKill "${pids[@]}"
|
|
||||||
|
|
||||||
closeNetwork
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
startConsole() {
|
|
||||||
|
|
||||||
local output="${1:-/dev/tty}"
|
|
||||||
local cnt=0 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 >"$output"
|
|
||||||
) &
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
stopConsole() {
|
|
||||||
|
|
||||||
mKill "$CONSOLE_PID"
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
startQemu() {
|
|
||||||
|
|
||||||
rm -f -- "$QEMU_START_PID"
|
|
||||||
|
|
||||||
(
|
|
||||||
trap '' INT QUIT
|
|
||||||
|
|
||||||
# shellcheck disable=SC2016
|
|
||||||
exec setsid -f -w sh -c '
|
|
||||||
file=$1
|
|
||||||
shift
|
|
||||||
|
|
||||||
"$@" &
|
|
||||||
pid=$!
|
|
||||||
printf "%s\n" "$pid" > "$file" || exit 1
|
|
||||||
|
|
||||||
rc=0
|
|
||||||
wait "$pid" 2>/dev/null || rc=$?
|
|
||||||
exit "$rc"
|
|
||||||
' sh "$QEMU_START_PID" "$@"
|
|
||||||
) </dev/null &
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
finish() {
|
finish() {
|
||||||
|
|
||||||
local reason=$1 failed=0
|
local reason=$1 failed=0
|
||||||
@@ -327,7 +120,10 @@ finish() {
|
|||||||
markWindowsBooted
|
markWindowsBooted
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cleanupHelpers
|
cleanupHelpers \
|
||||||
|
"${SMB_PID:-}" \
|
||||||
|
"${NMB_PID:-}" \
|
||||||
|
"${DDN_PID:-}"
|
||||||
|
|
||||||
if ! waitQemuExit 10; then
|
if ! waitQemuExit 10; then
|
||||||
warn "Timed out while waiting for $(app) to exit!"
|
warn "Timed out while waiting for $(app) to exit!"
|
||||||
@@ -344,43 +140,6 @@ finish() {
|
|||||||
exit "$reason"
|
exit "$reason"
|
||||||
}
|
}
|
||||||
|
|
||||||
normalizeTimeout() {
|
|
||||||
|
|
||||||
local term_grace=3 # seconds before loop ends to send SIGTERM
|
|
||||||
local cleanup_grace=3 # seconds reserved after the loop for cleanup
|
|
||||||
|
|
||||||
TIMEOUT=$(strip "$TIMEOUT")
|
|
||||||
if [[ ! "$TIMEOUT" =~ ^[0-9]+$ ]]; then
|
|
||||||
TIMEOUT=105
|
|
||||||
fi
|
|
||||||
|
|
||||||
if (( TIMEOUT >= 30 )); then
|
|
||||||
term_grace=5
|
|
||||||
cleanup_grace=5
|
|
||||||
elif (( TIMEOUT >= 15 )); then
|
|
||||||
term_grace=4
|
|
||||||
cleanup_grace=4
|
|
||||||
fi
|
|
||||||
|
|
||||||
local min=$((term_grace + cleanup_grace + 1))
|
|
||||||
(( TIMEOUT < min )) && (( TIMEOUT = min ))
|
|
||||||
|
|
||||||
wait_until=$((TIMEOUT - cleanup_grace))
|
|
||||||
sigterm_at=$((wait_until - term_grace))
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
sendAcpiShutdown() {
|
|
||||||
|
|
||||||
[ ! -S "$QEMU_DIR/monitor.sock" ] && return 0
|
|
||||||
|
|
||||||
# Send ACPI shutdown signal
|
|
||||||
nc -q 1 -w 1 -U "$QEMU_DIR/monitor.sock" &> /dev/null <<<'system_powerdown' || :
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
abortDuringSetup() {
|
abortDuringSetup() {
|
||||||
|
|
||||||
local code="$1"
|
local code="$1"
|
||||||
@@ -396,41 +155,7 @@ abortDuringSetup() {
|
|||||||
finish "$code"
|
finish "$code"
|
||||||
}
|
}
|
||||||
|
|
||||||
waitForShutdown() {
|
gracefulShutdown() {
|
||||||
|
|
||||||
local pid="$1"
|
|
||||||
local name="$APP"
|
|
||||||
local slp cnt=0
|
|
||||||
|
|
||||||
while (( cnt <= wait_until && SHUTDOWN_SKIP == 0 )); do
|
|
||||||
|
|
||||||
sleep 1 &
|
|
||||||
slp=$!
|
|
||||||
|
|
||||||
# Stop waiting if the process has exited
|
|
||||||
! isAlive "$pid" && break
|
|
||||||
|
|
||||||
# Workaround for stale/zombie QEMU pid file
|
|
||||||
[ ! -s "$QEMU_START_PID" ] && [ ! -s "$QEMU_PID" ] && break
|
|
||||||
|
|
||||||
if (( cnt == sigterm_at )); then
|
|
||||||
info "${name^} is still running, sending SIGTERM... ($cnt/$wait_until)"
|
|
||||||
kill -15 -- "$pid" 2>/dev/null || :
|
|
||||||
elif (( cnt > 0 )); then
|
|
||||||
info "Waiting for $name to shut down... ($cnt/$wait_until)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
sendAcpiShutdown
|
|
||||||
|
|
||||||
wait "$slp" || :
|
|
||||||
(( cnt++ ))
|
|
||||||
|
|
||||||
done
|
|
||||||
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
graceful_shutdown() {
|
|
||||||
|
|
||||||
local sig="$1"
|
local sig="$1"
|
||||||
local pid="" code=0
|
local pid="" code=0
|
||||||
@@ -473,7 +198,7 @@ graceful_shutdown() {
|
|||||||
abortDuringSetup "$code"
|
abortDuringSetup "$code"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
normalizeTimeout
|
normalizeTimeout 105
|
||||||
waitForShutdown "$pid"
|
waitForShutdown "$pid"
|
||||||
|
|
||||||
finish "$code"
|
finish "$code"
|
||||||
@@ -483,9 +208,9 @@ graceful_shutdown() {
|
|||||||
[ -n "${QEMU_TIMEOUT:-}" ] && TIMEOUT="$QEMU_TIMEOUT"
|
[ -n "${QEMU_TIMEOUT:-}" ] && TIMEOUT="$QEMU_TIMEOUT"
|
||||||
|
|
||||||
if interactive; then
|
if interactive; then
|
||||||
_trap graceful_shutdown SIGINT
|
_trap gracefulShutdown SIGINT
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_trap graceful_shutdown SIGTERM SIGHUP SIGABRT SIGQUIT
|
_trap gracefulShutdown SIGTERM SIGHUP SIGABRT SIGQUIT
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
Reference in New Issue
Block a user