etc: Allow init.d/ashd to handle remaining connections more gracefully.
authorFredrik Tolf <fredrik@dolda2000.com>
Fri, 14 May 2021 14:29:11 +0000 (16:29 +0200)
committerFredrik Tolf <fredrik@dolda2000.com>
Fri, 14 May 2021 14:29:11 +0000 (16:29 +0200)
etc/debian/init.d-ashd

index 9fd1e42..9ef1568 100755 (executable)
@@ -15,6 +15,9 @@ set -e
 PATH=/usr/local/bin:/usr/local/sbin:$PATH
 HTPARSER="$(which htparser || true)"
 PIDFILE=/var/run/ashd.pid
+GRACE_PERIOD=10
+USER=nobody
+CHROOT=/var/tmp
 PORTSPEC="plain"
 ROOTSPEC="dirplex /srv/www"
 [ -r /etc/default/locale ] && . /etc/default/locale
@@ -24,25 +27,91 @@ ROOTSPEC="dirplex /srv/www"
 start() {
     export LANG
     log_daemon_msg "Starting HTTP server" "ashd"
-    start-stop-daemon -S -p "$PIDFILE" -qx "$HTPARSER" -- -Sf -p "$PIDFILE" -u nobody -r /var/tmp $PORTSPEC -- $ROOTSPEC
-    log_end_msg $?
+    if start-stop-daemon -S -p "$PIDFILE" -qa "$HTPARSER" -- -Sf -p "$PIDFILE" -u "$USER" -r "$CHROOT" $PORTSPEC -- $ROOTSPEC; then
+       log_success_msg
+    else
+       log_end_msg $?
+    fi
 }
 
-stop() {
-    log_daemon_msg "Stopping HTTP server" "ashd"
+kill_wholly() {
+    start-stop-daemon -K -p "$PIDFILE" -qx "$HTPARSER"
+}
+
+kill_listen() {
+    pid=$(cat "$PIDFILE" 2>/dev/null || true)
+    if [ -z "$pid" ]; then
+       log_failure_msg "no pid file"
+       return 1
+    fi
+    if ! kill -0 "$pid"; then
+       log_failure_msg "invalid saved pid"
+       return 1
+    fi
+    log_progress_msg "listen"
+    kill -TERM "$pid"
+    for try in 0 1 2 3 4 5; do
+         sleep $try
+         case "$(wc -l <"$PIDFILE")" in
+             1) continue ;;
+             0|2) return 0 ;;
+             *)
+                 log_failure_msg "could not parse pid file"
+                 return 1
+                 ;;
+         esac
+    done
+    log_failure_msg "htparser did not stop listening, killing it completely"
+    kill_wholly
     start-stop-daemon -K -p "$PIDFILE" -qx "$HTPARSER"
+    return 1
+}
+
+stop_listen() {
+    log_daemon_msg "Stopping HTTP server" "ashd"
+    kill_listen
     log_end_msg $?
 }
 
+stop_gracefully() {
+    log_daemon_msg "Stopping HTTP server" "ashd"
+    if ! kill_listen ; then
+       log_end_msg $?
+       return 1
+    fi
+    pid=$(cat "$PIDFILE" 2>/dev/null || true)
+    if kill -0 "$pid" 2>/dev/null; then
+       log_progress_msg "waiting for remaining connections..."
+       for try in $(seq "$GRACE_PERIOD"); do
+           sleep 1
+           if ! kill -0 "$pid" 2>/dev/null; then
+               log_success_msg
+               return 0
+           fi
+       done
+    else
+       log_success_msg
+       return 0
+    fi
+    log_progress_msg "terminating remaining connections"
+    if kill_wholly; then
+       log_success_msg
+    else
+       log_end_msg $?
+    fi
+}
+
 case "$1" in
     start)
        start
        ;;
     stop)
-       stop
+       stop_gracefully
        ;;
     restart)
-       stop
+       stop_listen
+       # Truncate PID file to allow start-stop-daemon to work despite remaining connections.
+       >"$PIDFILE"
        start
        ;;
 esac