diff --git a/lib/common/watchdog.c b/lib/common/watchdog.c
index b7921fe87a..3340bc616e 100644
--- a/lib/common/watchdog.c
+++ b/lib/common/watchdog.c
@@ -1,319 +1,319 @@
 /*
  * Copyright 2013-2024 the Pacemaker project contributors
  *
  * The version control history for this file may have further details.
  *
  * This source code is licensed under the GNU Lesser General Public License
  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
  */
 
 #include <crm_internal.h>
 
 #include <sched.h>
 #include <sys/ioctl.h>
 #include <sys/reboot.h>
 
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
 #include <ctype.h>
 #include <dirent.h>
 #include <signal.h>
 
 static pid_t sbd_pid = 0;
 
 static void
 sysrq_trigger(char t)
 {
 #if HAVE_LINUX_PROCFS
     FILE *procf;
 
     // Root can always write here, regardless of kernel.sysrq value
     procf = fopen("/proc/sysrq-trigger", "a");
     if (!procf) {
         crm_perror(LOG_WARNING, "Opening sysrq-trigger failed");
         return;
     }
     crm_info("sysrq-trigger: %c", t);
     fprintf(procf, "%c\n", t);
     fclose(procf);
 #endif // HAVE_LINUX_PROCFS
     return;
 }
 
 
 /*!
  * \internal
  * \brief Panic the local host (if root) or tell pacemakerd to do so
  */
 static void
 panic_local(void)
 {
     int rc = pcmk_ok;
     uid_t uid = geteuid();
     pid_t ppid = getppid();
     const char *panic_action = pcmk__env_option(PCMK__ENV_PANIC_ACTION);
 
+    // Default panic action is to reboot
+    char sysrq = 'b';
+    int reboot_cmd = RB_AUTOBOOT;
+
     if(uid != 0 && ppid > 1) {
         /* We're a non-root pacemaker daemon (pacemaker-based,
          * pacemaker-controld, pacemaker-schedulerd, pacemaker-attrd, etc.) with
          * the original pacemakerd parent.
          *
          * Of these, only the controller is likely to be initiating resets.
          */
         crm_emerg("Signaling parent %lld to panic", (long long) ppid);
         crm_exit(CRM_EX_PANIC);
         return;
 
     } else if (uid != 0) {
 #if HAVE_LINUX_PROCFS
         /*
          * No permissions, and no pacemakerd parent to escalate to.
          * Track down the new pacemakerd process and send a signal instead.
          */
         union sigval signal_value;
 
         memset(&signal_value, 0, sizeof(signal_value));
         ppid = pcmk__procfs_pid_of("pacemakerd");
         crm_emerg("Signaling pacemakerd[%lld] to panic", (long long) ppid);
 
         if(ppid > 1 && sigqueue(ppid, SIGQUIT, signal_value) < 0) {
             crm_perror(LOG_EMERG, "Cannot signal pacemakerd[%lld] to panic",
                        (long long) ppid);
         }
 #endif // HAVE_LINUX_PROCFS
 
         /* The best we can do now is die */
         crm_exit(CRM_EX_PANIC);
         return;
     }
 
     /* We're either pacemakerd, or a pacemaker daemon running as root */
 
-    if (pcmk__str_eq(panic_action, "crash", pcmk__str_casei)) {
-        sysrq_trigger('c');
-
-    } else if (pcmk__str_eq(panic_action, "sync-crash", pcmk__str_casei)) {
+    if (pcmk__starts_with(panic_action, "sync-")) {
         sync();
-        sysrq_trigger('c');
+        panic_action += strlen("sync-");
+    };
 
-    } else {
-        if (pcmk__str_eq(panic_action, "sync-reboot", pcmk__str_casei)) {
-            sync();
-        }
-        sysrq_trigger('b');
+    if (pcmk__str_eq(panic_action, "crash", pcmk__str_casei)) {
+        sysrq = 'c';
     }
-    /* reboot(RB_HALT_SYSTEM); rc = errno; */
-    reboot(RB_AUTOBOOT);
+
+    sysrq_trigger(sysrq);
+    reboot(reboot_cmd);
     rc = errno;
 
     crm_emerg("Reboot failed, escalating to parent %lld: %s " CRM_XS " rc=%d",
               (long long) ppid, pcmk_rc_str(rc), rc);
 
     if(ppid > 1) {
         /* child daemon */
         crm_exit(CRM_EX_PANIC);
     } else {
         /* pacemakerd or orphan child */
         crm_exit(CRM_EX_FATAL);
     }
 }
 
 /*!
  * \internal
  * \brief Tell sbd to kill the local host, then exit
  */
 static void
 panic_sbd(void)
 {
     union sigval signal_value;
     pid_t ppid = getppid();
 
     crm_emerg("Signaling sbd[%lld] to panic", (long long) sbd_pid);
 
     memset(&signal_value, 0, sizeof(signal_value));
     /* TODO: Arrange for a slightly less brutal option? */
     if(sigqueue(sbd_pid, SIGKILL, signal_value) < 0) {
         crm_perror(LOG_EMERG, "Cannot signal sbd[%lld] to terminate",
                    (long long) sbd_pid);
         panic_local();
     }
 
     if(ppid > 1) {
         /* child daemon */
         crm_exit(CRM_EX_PANIC);
     } else {
         /* pacemakerd or orphan child */
         crm_exit(CRM_EX_FATAL);
     }
 }
 
 /*!
  * \internal
  * \brief Panic the local host
  *
  * Panic the local host either by sbd (if running), directly, or by asking
  * pacemakerd. If trace logging this function, exit instead.
  *
  * \param[in] origin   Function caller (for logging only)
  */
 void
 pcmk__panic(const char *origin)
 {
     /* Ensure sbd_pid is set */
     (void) pcmk__locate_sbd();
 
     pcmk__if_tracing(
         {
             // getppid() == 1 means our original parent no longer exists
             crm_emerg("Shutting down instead of panicking the node "
                       CRM_XS " origin=%s sbd=%lld parent=%d",
                       origin, (long long) sbd_pid, getppid());
             crm_exit(CRM_EX_FATAL);
             return;
         },
         {}
     );
 
     if(sbd_pid > 1) {
         crm_emerg("Signaling sbd[%lld] to panic the system: %s",
                   (long long) sbd_pid, origin);
         panic_sbd();
 
     } else {
         crm_emerg("Panicking the system directly: %s", origin);
         panic_local();
     }
 }
 
 /*!
  * \internal
  * \brief Return the process ID of sbd (or 0 if it is not running)
  */
 pid_t
 pcmk__locate_sbd(void)
 {
     char *pidfile = NULL;
     char *sbd_path = NULL;
     int rc;
 
     if(sbd_pid > 1) {
         return sbd_pid;
     }
 
     /* Look for the pid file */
     pidfile = crm_strdup_printf(PCMK_RUN_DIR "/sbd.pid");
     sbd_path = crm_strdup_printf("%s/sbd", SBIN_DIR);
 
     /* Read the pid file */
     rc = pcmk__pidfile_matches(pidfile, 0, sbd_path, &sbd_pid);
     if (rc == pcmk_rc_ok) {
         crm_trace("SBD detected at pid %lld (via PID file %s)",
                   (long long) sbd_pid, pidfile);
 
 #if HAVE_LINUX_PROCFS
     } else {
         /* Fall back to /proc for systems that support it */
         sbd_pid = pcmk__procfs_pid_of("sbd");
         crm_trace("SBD detected at pid %lld (via procfs)",
                   (long long) sbd_pid);
 #endif // HAVE_LINUX_PROCFS
     }
 
     if(sbd_pid < 0) {
         sbd_pid = 0;
         crm_trace("SBD not detected");
     }
 
     free(pidfile);
     free(sbd_path);
 
     return sbd_pid;
 }
 
 long
 pcmk__get_sbd_watchdog_timeout(void)
 {
     static long sbd_timeout = -2;
 
     if (sbd_timeout == -2) {
         sbd_timeout = crm_get_msec(getenv("SBD_WATCHDOG_TIMEOUT"));
     }
     return sbd_timeout;
 }
 
 bool
 pcmk__get_sbd_sync_resource_startup(void)
 {
     static int sync_resource_startup = PCMK__SBD_SYNC_DEFAULT;
     static bool checked_sync_resource_startup = false;
 
     if (!checked_sync_resource_startup) {
         const char *sync_env = getenv("SBD_SYNC_RESOURCE_STARTUP");
 
         if (sync_env == NULL) {
             crm_trace("Defaulting to %sstart-up synchronization with sbd",
                       (PCMK__SBD_SYNC_DEFAULT? "" : "no "));
 
         } else if (crm_str_to_boolean(sync_env, &sync_resource_startup) < 0) {
             crm_warn("Defaulting to %sstart-up synchronization with sbd "
                      "because environment value '%s' is invalid",
                      (PCMK__SBD_SYNC_DEFAULT? "" : "no "), sync_env);
         }
         checked_sync_resource_startup = true;
     }
     return sync_resource_startup != 0;
 }
 
 long
 pcmk__auto_stonith_watchdog_timeout(void)
 {
     long sbd_timeout = pcmk__get_sbd_watchdog_timeout();
 
     return (sbd_timeout <= 0)? 0 : (2 * sbd_timeout);
 }
 
 bool
 pcmk__valid_stonith_watchdog_timeout(const char *value)
 {
     /* @COMPAT At a compatibility break, accept either negative values or a
      * specific string like "auto" (but not both) to mean "auto-calculate the
      * timeout." Reject other values that aren't parsable as timeouts.
      */
     long st_timeout = value? crm_get_msec(value) : 0;
 
     if (st_timeout < 0) {
         st_timeout = pcmk__auto_stonith_watchdog_timeout();
         crm_debug("Using calculated value %ld for "
                   PCMK_OPT_STONITH_WATCHDOG_TIMEOUT " (%s)",
                   st_timeout, value);
     }
 
     if (st_timeout == 0) {
         crm_debug("Watchdog may be enabled but "
                   PCMK_OPT_STONITH_WATCHDOG_TIMEOUT " is disabled (%s)",
                   value? value : "default");
 
     } else if (pcmk__locate_sbd() == 0) {
         crm_emerg("Shutting down: " PCMK_OPT_STONITH_WATCHDOG_TIMEOUT
                   " configured (%s) but SBD not active",
                   pcmk__s(value, "auto"));
         crm_exit(CRM_EX_FATAL);
         return false;
 
     } else {
         long sbd_timeout = pcmk__get_sbd_watchdog_timeout();
 
         if (st_timeout < sbd_timeout) {
             crm_emerg("Shutting down: " PCMK_OPT_STONITH_WATCHDOG_TIMEOUT
                       " (%s) too short (must be >%ldms)",
                       value, sbd_timeout);
             crm_exit(CRM_EX_FATAL);
             return false;
         }
         crm_info("Watchdog configured with " PCMK_OPT_STONITH_WATCHDOG_TIMEOUT
                  " %s and SBD timeout %ldms",
                  value, sbd_timeout);
     }
     return true;
 }