QElectroTech 0.200.1-dev
Loading...
Searching...
No Matches
EventLoopWatchdog Class Reference

The EventLoopWatchdog class Detects when the main (GUI) thread's event loop goes unresponsive – QetLogger (discussion #644) can only see what an explicit qDebug()/ qInfo()/qWarning() call already decided to report, and most of a session (painting, dragging, a slow synchronous operation) produces no log output at all, so a silent multi-second gap in the log is indistinguishable from the user simply not doing anything. More...

#include <eventloopwatchdog.h>

Inherits QObject.

Collaboration diagram for EventLoopWatchdog:
Collaboration graph

Public Member Functions

 EventLoopWatchdog (QObject *parent=nullptr)
void start ()

Static Public Attributes

static constexpr int kTickIntervalMs = 50
static constexpr int kStallThresholdMs = 200

Private Slots

void tick ()

Private Attributes

QTimer m_timer
QElapsedTimer m_elapsed
bool m_disabled = false

Detailed Description

The EventLoopWatchdog class Detects when the main (GUI) thread's event loop goes unresponsive – QetLogger (discussion #644) can only see what an explicit qDebug()/ qInfo()/qWarning() call already decided to report, and most of a session (painting, dragging, a slow synchronous operation) produces no log output at all, so a silent multi-second gap in the log is indistinguishable from the user simply not doing anything.

This closes that gap the direct way: a repeating QTimer::PreciseTimer ticks on a short, fixed interval; each tick measures the actual wall-clock time elapsed since the previous one via QElapsedTimer (monotonic – unaffected by system clock/NTP adjustments, unlike QDateTime). Qt does not queue up missed fires for a normal repeating timer, so if the event loop is blocked for 600ms, the timer fires once as soon as the loop frees up, with ~600ms measured since the last tick – that gap is the stall, measured at its source rather than inferred from log silence.

Only fires a qWarning() (and so only touches the log at all) when a tick is late by more than kStallThresholdMs, to stay within the spirit of QetLogger's bounded-log design (see its class comment) – a healthy session should produce zero output from this class. This tells you that a stall happened and how long it was, not what caused it; pair a reported timestamp with docker exec+gdb the way the CLI hang (PR #661) was diagnosed to go from "it lagged" to a root cause.

Escape hatch: if QET_WATCHDOG_DISABLE=1 is set in the environment at construction time, start() does nothing.

Constructor & Destructor Documentation

◆ EventLoopWatchdog()

EventLoopWatchdog::EventLoopWatchdog ( QObject * parent = nullptr)
explicit
Here is the call graph for this function:

Member Function Documentation

◆ start()

void EventLoopWatchdog::start ( )

Starts ticking. Must be called from the main thread, after the event loop it watches is about to run (i.e. immediately before QApplication::exec()) – constructing this class earlier is harmless, but start() before there is an event loop to tick against would just measure the time until app.exec() is reached. No-op if QET_WATCHDOG_DISABLE=1 was set at construction time.

Here is the caller graph for this function:

◆ tick

void EventLoopWatchdog::tick ( )
privateslot
Here is the caller graph for this function:

Member Data Documentation

◆ kStallThresholdMs

int EventLoopWatchdog::kStallThresholdMs = 200
staticconstexpr

A tick arriving later than this many ms after the previous one is logged as a stall. Comfortably above kTickIntervalMs so ordinary OS scheduling noise doesn't produce a warning on every tick, and in the range a user would actually notice as lag.

◆ kTickIntervalMs

int EventLoopWatchdog::kTickIntervalMs = 50
staticconstexpr

How often the watchdog checks in. Small enough to bound the measurement's own granularity, large enough that the tick itself is negligible overhead on the event loop it's watching.

◆ m_disabled

bool EventLoopWatchdog::m_disabled = false
private

◆ m_elapsed

QElapsedTimer EventLoopWatchdog::m_elapsed
private

◆ m_timer

QTimer EventLoopWatchdog::m_timer
private

The documentation for this class was generated from the following files: