Skip to content

Fix DCHECK(handle) crash in CefMessageRouter.cancelPending(null, null) - #39

Merged
Thrameos merged 1 commit into
masterfrom
backport/message-router-cancelpending-null
Sep 6, 2026
Merged

Thrameos merged 1 commit into
masterfrom
backport/message-router-cancelpending-null

Conversation

@Thrameos

@Thrameos Thrameos commented Sep 5, 2026

Copy link
Copy Markdown
Owner

Summary

  • CefMessageRouter_N.cpp's local GetHandler() unconditionally constructed a ScopedJNIObject over jrouterHandler before checking it, even though cancelPending()'s own Javadoc documents the handler as nullable.
  • That constructor DCHECKs its handle is non-null, so a null handler crashed the process.
  • GetJNIBrowser()/GetCefFromJNIObject_sync() already null-checks its own argument, so only the routerHandler side needed the guard. Fixed by short-circuiting GetHandler() on a null handle before it ever reaches ScopedJNIObject's non-null-handle constructor.

Test plan

  • Added CefMessageRouterTest with a regression case exercising cancelPending(null, null) (the crashing input).
  • Rebuilt libjcef.so cleanly (ninja jcef), zero compile errors.
  • Full local suite run: 125/125 tests passing, including the new regression test.

Small, focused backport of a single self-contained fix (no other changes bundled in), following the same shape as PR #1, #36, #37, #38.

🤖 Generated with Claude Code

https://claude.ai/code/session_01HBFmQs6JDypYP5qdC99yDq

@Thrameos Thrameos mentioned this pull request Sep 5, 2026
3 tasks done
@codecov

codecov Bot commented Sep 5, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 38.50%. Comparing base (be68fe1) to head (4d33800).

Additional details and impacted files
@@             Coverage Diff              @@
##             master      #39      +/-   ##
============================================
+ Coverage     38.01%   38.50%   +0.49%     
- Complexity      735      742       +7     
============================================
  Files           243      244       +1     
  Lines         14863    14882      +19     
  Branches       2449     2450       +1     
============================================
+ Hits           5650     5731      +81     
+ Misses         8011     7938      -73     
- Partials       1202     1213      +11     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Thrameos added a commit that referenced this pull request Sep 5, 2026
preliminary update racing ahead of onBeforeDownload

CefDownloadItemTest.cancelDuringDownloadInvokesNCancel() flaked
intermittently in CI across multiple unrelated backport PRs (#38, #39, #41,
#42), always failing the same assertion: "onBeforeDownload was never
invoked". Root-caused by reproducing it locally (100% deterministic once a
low-risk, narrowly-scoped repro was possible -- see PR #44's run_tests.sh
fix, needed first to run just this one test without also running the whole
suite + leak-sweep) and adding temporary native fprintf instrumentation
(not included in this commit) at DownloadHandler::OnBeforeDownload/
OnDownloadUpdated and ClientHandler::GetDownloadHandler.

That instrumentation showed CEF can deliver a preliminary
OnDownloadUpdated() notification -- for a valid, real CefDownloadItem --
*before* OnBeforeDownload() has been dispatched to the handler at all. This
test's onDownloadUpdated() used to treat "not complete" on the very first
update it saw as "must actively cancel it", immediately calling
callback.cancel() and terminateTest() -- racing ahead of onBeforeDownload
and ending the test before it ever got a chance to run, which is exactly
what "onBeforeDownload was never invoked" captures.

Fix: ignore any onDownloadUpdated() notification that arrives before this
handler's own onBeforeDownload() has recorded its decision
(gotBeforeDownload[0]). Verified via direct reproduction: failed 3/3 in
isolation before the fix (including against a heavily-used local CEF
profile where it failed 100% of the time), passed cleanly every time after
(5+ consecutive solo runs, plus the full class together) with no change to
downloadCompletesAndWritesRealFile's behavior.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01HBFmQs6JDypYP5qdC99yDq
CefMessageRouter_N.cpp's local GetHandler() unconditionally constructed a
ScopedJNIObject over jrouterHandler before checking it, even though
cancelPending()'s own Javadoc documents the handler as nullable. That
constructor DCHECKs its handle is non-null, so a null handler crashed the
process. GetJNIBrowser()/GetCefFromJNIObject_sync() already null-checks its
own argument, so only the routerHandler side needed the guard.

Adds CefMessageRouterTest with a regression case exercising
cancelPending(null, null). Verified against a full local suite run:
125/125 passing.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01HBFmQs6JDypYP5qdC99yDq
@Thrameos
Thrameos force-pushed the backport/message-router-cancelpending-null branch from 69b402e to 4d33800 Compare September 5, 2026 21:23
@Thrameos Thrameos added the bug Something isn't working label Sep 6, 2026
@Thrameos
Thrameos merged commit d88d365 into master Sep 6, 2026
9 checks passed
@Thrameos
Thrameos deleted the backport/message-router-cancelpending-null branch September 6, 2026 03:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant