diff --git a/src/check.sh b/src/check.sh index 3143152..a8769e6 100644 --- a/src/check.sh +++ b/src/check.sh @@ -3,8 +3,8 @@ set -Eeuo pipefail : ${VM_NET_DEV:='eth0'} -[ ! -f "/run/qemu.pid" ] && echo "QEMU not running yet.." && exit 0 [ -f "/run/qemu.count" ] && echo "QEMU is shutting down.." && exit 1 +[ ! -f "/run/qemu.pid" ] && echo "QEMU not running yet.." && exit 0 file="/run/dsm.url" [ ! -f "$file" ] && echo "DSM has not enabled networking yet.." && exit 1 diff --git a/src/entry.sh b/src/entry.sh index d9ba03f..f3ce438 100755 --- a/src/entry.sh +++ b/src/entry.sh @@ -23,12 +23,11 @@ if [[ "$CONSOLE" == [Yy]* ]]; then exit $? fi -set -m -( - [[ "$DEBUG" == [Yy1]* ]] && info "$VERS" && set -x - qemu-system-x86_64 ${ARGS:+ $ARGS} & echo $! > "$QEMU_PID" - { set +x; } 2>/dev/null -) -set +m +[[ "$DEBUG" == [Yy1]* ]] && info "$VERS" && set -x +qemu-system-x86_64 -daemonize -pidfile "$QEMU_PID" ${ARGS:+ $ARGS} -tail --pid "$(cat "$QEMU_PID")" --follow /dev/null & wait $! +{ set +x; } 2>/dev/null +cat /dev/pts/1 2>/dev/null & wait $! || true + +sleep 1 +finish 0 diff --git a/src/network.sh b/src/network.sh index 82bd008..7beb10c 100644 --- a/src/network.sh +++ b/src/network.sh @@ -158,14 +158,14 @@ closeNetwork () { if [[ "$DHCP" == [Yy1]* ]]; then - { pkill -f server.sh || true; } 2>/dev/null + fKill "server.sh" ip link set "$VM_NET_TAP" down || true ip link delete "$VM_NET_TAP" || true else - { pkill -f dnsmasq || true; } 2>/dev/null + fKill "dnsmasq" ip link set "$VM_NET_TAP" down promisc off || true ip link delete "$VM_NET_TAP" || true @@ -180,7 +180,7 @@ closeNetwork () { # Configure Network # ###################################### -{ pkill -f server.sh || true; } 2>/dev/null +fKill "server.sh" # Create the necessary file structure for /dev/net/tun if [ ! -c /dev/net/tun ]; then diff --git a/src/power.sh b/src/power.sh index 6f64018..54965db 100644 --- a/src/power.sh +++ b/src/power.sh @@ -3,38 +3,88 @@ set -Eeuo pipefail # Configure QEMU for graceful shutdown +API_CMD=6 +API_TIMEOUT=50 +API_HOST="127.0.0.1:2210" + QEMU_PORT=7100 -QEMU_TIMEOUT=55 +QEMU_TIMEOUT=50 QEMU_PID="/run/qemu.pid" QEMU_COUNT="/run/qemu.count" +if [[ "$KVM" == [Nn]* ]]; then + API_TIMEOUT=$(( API_TIMEOUT*2 )) + QEMU_TIMEOUT=$(( QEMU_TIMEOUT*2 )) +fi + rm -f "$QEMU_PID" rm -f "$QEMU_COUNT" -_trap(){ - func="$1" ; shift - for sig ; do - trap "$func $sig" "$sig" +_trap() { + func="$1" ; shift + for sig ; do + trap "$func $sig" "$sig" + done +} + +finish() { + + local pid + local reason=$1 + + if [ -f "$QEMU_PID" ]; then + + pid="$(cat "$QEMU_PID")" + echo && error "Forcefully quitting QEMU process, reason: $reason..." + { kill -15 "$pid" || true; } 2>/dev/null + + while isAlive "$pid"; do + sleep 1 + # Workaround for zombie pid + [ ! -f "$QEMU_PID" ] && break done + fi + + fKill "print.sh" + fKill "host.bin" + + closeNetwork + + sleep 1 + echo && info "Shutdown completed!" + + exit "$reason" } _graceful_shutdown() { - set +e - local cnt response + local code=$? + local pid cnt response - [ ! -f "$QEMU_PID" ] && exit 130 [ -f "$QEMU_COUNT" ] && return - echo 0 > "$QEMU_COUNT" + + set +e echo && info "Received $1 signal, sending shutdown command..." + if [ ! -f "$QEMU_PID" ]; then + echo && error "QEMU PID file does not exist?" + finish "$code" && return "$code" + fi + + pid="$(cat "$QEMU_PID")" + + if ! isAlive "$pid"; then + echo && error "QEMU process does not exist?" + finish "$code" && return "$code" + fi + # Don't send the powerdown signal because vDSM ignores ACPI signals # echo 'system_powerdown' | nc -q 1 -w 1 localhost "${QEMU_PORT}" > /dev/null # Send shutdown command to guest agent via serial port - url="http://127.0.0.1:2210/read?command=6&timeout=50" - response=$(curl -sk -m 52 -S "$url" 2>&1) + url="http://$API_HOST/read?command=$API_CMD&timeout=$API_TIMEOUT" + response=$(curl -sk -m "$(( API_TIMEOUT+2 ))" -S "$url" 2>&1) if [[ "$response" =~ "\"success\"" ]]; then @@ -43,19 +93,17 @@ _graceful_shutdown() { else response="${response#*message\"\: \"}" - echo && error "Failed to send shutdown command: ${response%%\"*}" - - kill -15 "$(cat "$QEMU_PID")" - pkill -f qemu-system-x86_64 || true + [ -z "$response" ] && response="second signal" + echo && error "Forcefully quitting because of: ${response%%\"*}" + { kill -15 "$pid" || true; } 2>/dev/null fi while [ "$(cat $QEMU_COUNT)" -lt "$QEMU_TIMEOUT" ]; do - # Try to connect to qemu - if ! echo 'info version'| nc -q 1 -w 1 localhost "$QEMU_PORT" >/dev/null 2>&1 ; then - break - fi + ! isAlive "$pid" && break + + sleep 1 # Increase the counter cnt=$(($(cat $QEMU_COUNT)+1)) @@ -63,23 +111,16 @@ _graceful_shutdown() { [[ "$DEBUG" == [Yy1]* ]] && info "Shutting down, waiting... ($cnt/$QEMU_TIMEOUT)" + # Workaround for zombie pid + [ ! -f "$QEMU_PID" ] && break + done if [ "$(cat $QEMU_COUNT)" -ge "$QEMU_TIMEOUT" ]; then - echo && error "Shutdown timeout reached, forcefully quitting.." - else - echo && echo "❯ Quitting..." + echo && error "Shutdown timeout reached!" fi - echo 'quit' | nc -q 1 -w 1 localhost "$QEMU_PORT" >/dev/null 2>&1 || true - - { pkill -f print.sh || true; } 2>/dev/null - { pkill -f host.bin || true; } 2>/dev/null - - closeNetwork - sleep 1 - - return + finish "$code" && return "$code" } _trap _graceful_shutdown SIGTERM SIGHUP SIGINT SIGABRT SIGQUIT diff --git a/src/reset.sh b/src/reset.sh index 54e3831..933e868 100644 --- a/src/reset.sh +++ b/src/reset.sh @@ -49,8 +49,41 @@ rm -rf "$STORAGE/tmp" # Helper functions -getCountry () { +isAlive() { + local pid=$1 + if kill -0 "$pid" 2>/dev/null; then + return 0 + fi + + return 1 +} + +pKill() { + local pid=$1 + + { kill -15 "$pid" || true; } 2>/dev/null + + while isAlive "$pid"; do + sleep 0.1 + done + + return 0 +} + +fKill () { + local name=$1 + + { pkill -f "$name" || true; } 2>/dev/null + + while pgrep -f -l "$name" >/dev/null; do + sleep 0.1 + done + + return 0 +} + +getCountry () { local url=$1 local query=$2 local rc json result @@ -87,7 +120,6 @@ setCountry () { } addPackage () { - local pkg=$1 local desc=$2 diff --git a/src/serial.sh b/src/serial.sh index 44796df..2f89e59 100644 --- a/src/serial.sh +++ b/src/serial.sh @@ -47,10 +47,9 @@ done # Configure serial ports SERIAL_OPTS="\ - -serial mon:stdio \ - -device virtio-serial-pci,id=virtio-serial0,bus=pcie.0,addr=0x3 \ -chardev pty,id=charserial0 \ -device isa-serial,chardev=charserial0,id=serial0 \ + -device virtio-serial-pci,id=virtio-serial0,bus=pcie.0,addr=0x3 \ -chardev socket,id=charchannel0,host=127.0.0.1,port=12345,reconnect=10 \ -device virtserialport,bus=virtio-serial0.0,nr=1,chardev=charchannel0,id=channel0,name=vchannel"