Re: watchdog timer programming

From: Stephane Rochoy <stephane.rochoy_at_stormshield.eu>
Date: Tue, 01 Oct 2024 06:07:28 UTC
mike tancsa <mike@sentex.net> writes:

> WARNING: This e-mail comes from someone outside your 
> organisation. Do not click
> on links or open attachments if you do not know the sender and 
> are not sure that
> the content is safe.
>
> On 9/30/2024 3:18 AM, Stephane Rochoy wrote:
>>
>> mike tancsa <mike@sentex.net> writes:
>>
>>> Do you know off hand how to set the system to just reboot ? 
>>> The ddb man
>>> page seems to imply I need options DDB as well, which is not 
>>> in GENERIC
>>> in order to set script actions.
>>
>> I would try the following:
>>
>>  ddb script kdb.enter.default=reset
>>
> If I build a custom kernel then that will work. But with GENERIC 
> (I am
> tracking project via freebsd-update), it fails
>
> # ddb script kdb.enter.default=reset
> ddb: sysctl: debug.ddb.scripting.scripts: No such file or 
> directory
>
> With a customer kernel, adding
>
> options DDB
>
> it works perfectly.
>
> Is there any way to get this to work without having ddb custom
> compiled in ?

I don't understand what's happening here. AFAIK, the code
corresponding to the soft watchdog being triggered is the
following:

  static void
  wd_timeout_cb(void *arg)
  {
    const char *type = arg;

  #ifdef DDB
    if ((wd_pretimeout_act & WD_SOFT_DDB)) {
      char kdb_why[80];
      snprintf(kdb_why, sizeof(kdb_why), "watchdog %s-timeout", 
      type);
      kdb_backtrace();
      kdb_enter(KDB_WHY_WATCHDOG, kdb_why);
    }
  #endif
    if ((wd_pretimeout_act & WD_SOFT_LOG))
      log(LOG_EMERG, "watchdog %s-timeout, WD_SOFT_LOG\n", type);
    if ((wd_pretimeout_act & WD_SOFT_PRINTF))
      printf("watchdog %s-timeout, WD_SOFT_PRINTF\n", type);
    if ((wd_pretimeout_act & WD_SOFT_PANIC))
      panic("watchdog %s-timeout, WD_SOFT_PANIC set", type);
  }

So without DDB, it should call panic. But in your case, it
called kdb_backtrace. So initial hypothesis was wrong. What I
missed is that panic was natively able to kdb_backtrace if gently
asked to do so:

  #ifdef KDB
    if ((newpanic || trace_all_panics) && trace_on_panic)
      kdb_backtrace();
    if (debugger_on_panic)
      kdb_enter(KDB_WHY_PANIC, "panic");
    else if (!newpanic && debugger_on_recursive_panic)
      kdb_enter(KDB_WHY_PANIC, "re-panic");
  #endif
    /*thread_lock(td); */
    td->td_flags |= TDF_INPANIC;
    /* thread_unlock(td); */
    if (!sync_on_panic)
      bootopt |= RB_NOSYNC;
    if (poweroff_on_panic)
      bootopt |= RB_POWEROFF;
    if (powercycle_on_panic)
      bootopt |= RB_POWERCYCLE;
    kern_reboot(bootopt);

So it definitely should reboot but as it don't, maybe playing with
kern.powercycle_on_panic would help?

Regards,
--  
Stéphane Rochoy
O: Stormshield