Skip to content

Fix dropped kernel messages and stale state between driver loads#413

Open
wjhwjhn wants to merge 1 commit intoCobaltFusion:developfrom
wjhwjhn:fix/kernel-reader-dropped-messages
Open

Fix dropped kernel messages and stale state between driver loads#413
wjhwjhn wants to merge 1 commit intoCobaltFusion:developfrom
wjhwjhn:fix/kernel-reader-dropped-messages

Conversation

@wjhwjhn
Copy link
Copy Markdown

@wjhwjhn wjhwjhn commented May 8, 2026

Hi! First of all, thanks for keeping DebugView++ alive — it's been a daily tool for me for a long time.

On my machine I was seeing kernel-mode messages arrive with visible latency, and the occasional message going missing when the driver produced a burst. I spent some time looking at what KernelReader does today and comparing it with Sysinternals DbgView to understand what was going on, and I wanted to share what I found in case it's useful.

The driver doesn't expose an event handle and DBGV_READ_LOG is a synchronous IOCTL, so both viewers end up polling. A couple of small things in KernelReader's current shape looked like they could probably be tightened up:

  • PolledLogSource::pollFrequency is in Hz, so the current value 1 means one poll per second, which seems to explain most of the latency I was seeing. Bumping it to 1000 (≈1 ms interval) helps a lot, and I added timeBeginPeriod(1) / timeEndPeriod(1) so the 1 ms sleep isn't rounded up to the default scheduler tick. That's why winmm is linked in CMake now — happy to split that out if you'd prefer.
  • Poll() issued a single DBGV_READ_LOG per tick, so if the driver produced more than one buffer-worth between polls, the rest got dropped. I changed it to drain the ring until the driver reports 0 bytes, which mirrors what DbgView's read loop does (it tight-loops the IOCTL until empty, bounded by a 300 ms budget, before yielding).
  • DBGV_CLEAR_DISPLAY is now sent before DBGV_CAPTURE_KERNEL so stale events from a previous session aren't replayed into the new one. DbgView does the same on startup.
  • On shutdown, verbose / pass-through bits are cleared before DBGV_UNCAPTURE_KERNEL, and m_pBuf is nulled after free to avoid a dangling pointer if start/stop is repeated.

I'm very open to changing any of this — I've only been in this code briefly, so if any of the above is wrong about the design intent, or there's a different direction you'd prefer, I'd be happy to revise. Thanks again for taking a look!

…apture state on start/stop

Raised the KernelReader poll rate from 1Hz to 1kHz, drained the driver ring per poll instead of reading one buffer and returning, and reset verbose/pass-through plus issued DBGV_CLEAR_DISPLAY around capture so state doesn't leak between driver loads.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant