Skip to main content

Module facility

Module facility 

Source
Expand description

What keeps a facility thread alive, and what is said when one dies.

Three single-purpose worker threads carry every deferred and timed operation this runtime offers: the delayed-callback timer (super::delayed_timer) behind sleep, interval, scan periods and callbackRequestDelayed; the scanOnce worker (super::scan_once) behind FLNK and scanOnce; and the callback bands (super::callback_executor). Each owns a Mutex + Condvar queue and runs callbacks its callers supplied. Two defects follow from that shape, and they were the same defect in all three files:

  • .lock().unwrap() propagates a poisoned mutex. Poison means “a thread panicked while holding this”, not “the data is broken” — these queues are plain collections whose invariants survive a panic — so propagating turns one caller’s panic into the loss of the whole facility.
  • A caller-supplied callback runs on the facility thread. An unwinding callback therefore unwinds the loop and the thread ends. Nothing announces it: submitters keep enqueueing, the IOC keeps answering CA and PVA, and every timed operation has simply stopped. An operator sees a healthy IOC whose records no longer process.

C reaches neither state: there is no unwinding, and callbackTask (callback.c:210-235) cannot be ended by the callback it invoked.

On a target built with panic = "abort" the two catch_unwinds here never catch and the process aborts instead. That is a different outcome but not a silent one, which is the property being defended.

Functions§

recover
Take a lock whose data outlives a panic — the only lock accessor these facilities use.
run_isolated
Run one caller-supplied callback on a facility thread so that a panic inside it costs that callback and nothing else.