Skip to content

fix: raise tao to 0.37.1 to remove the keyboard reentrancy deadlock (#2817) - #2819

Merged
mblua merged 7 commits into
mainfrom
fix/2817-tauri-keyboard-deadlock
Oct 2, 2026
Merged

mblua merged 7 commits into
mainfrom
fix/2817-tauri-keyboard-deadlock

Conversation

@mblua

@mblua mblua commented Oct 1, 2026 •

Copy link
Copy Markdown
Owner

Closes #2817

Reported problem and the upstream defect this change removes

Issue #2817 reports the interface freezing.

The approved plan's reading of upstream source is that tao 0.34.8 holds a global non-reentrant mutex (KEY_EVENT_BUILDERS) while its WM_KEYUP branch calls PeekMessageW. That peek can deliver pending sent messages, so a WM_KILLFOCUS arriving at that instant reenters the same callback on a thread that already holds the mutex. By the same reading, tao 0.37.1 no longer does this; T2 exercises that sequence on 0.37.1.

This is an analysis of the dependency's code, not a proven cause of the reported freeze. The freeze was not reproduced on the old version, so this PR does not show that this defect is what the user hit. It removes a defect that fits the report.

Change: seven paths, no application code

Relative to main at 070e7aa91c506d084a0746cbb436e5a9db0d0211:

  • src-tauri/Cargo.toml: tauri set to 2.12.1; Windows-only dev-dependency tao 0.37.1 for the harness.
  • Cargo.lock: resolves tauri 2.12.1 and a single tao 0.37.1.
  • src-tauri/tests/tao_keyboard_reentrancy.rs: T1 pins the resolved tao at >= 0.37.1. T2 (Windows) drives the reentrancy on a hidden window the test owns, bounded by a watchdog.
  • package-lock.json: @tauri-apps/api 2.10.1 to 2.12.1, so the JS API minor matches the crate.
  • crates/terminal-snapshot-renderer/tests/fixtures/diagnostic-failure-harness/Cargo.lock: fixture lock semver 1.0.27 to 1.0.28, so it stays a subset of the workspace lock.
  • src-tauri/tests/tauri_npm_version_coupling.rs: one test that fails when the tauri crate and @tauri-apps/api disagree on major.minor.
  • .github/workflows/g-fe-certification.yml: the hosted carrier that produces the frontend certification evidence set for this issue.

Integration with main, kept separate from the change

The branch contains four merges of main, never a rebase: 60184dde (of 2ed19c1c), 4856aa1e (of c0709653), ae35162b (of d9c7db92) and the head 181b76b1 (of 070e7aa9).

The last one brings in src/terminal/components/TerminalView.tsx from PR #2830 (#2829), two lines. That file is not part of this change. Two things a reader should know about it:

  • On PR fix: move terminal status strip to top-right (#2829) #2830 the frontend-regression job was skipped, so that file had no full frontend suite run on main.
  • This head is the first tree where that file sits together with @tauri-apps/api 2.12.1. Two runs executed the frontend suite on that combination, each with 269 test files and 3700 tests passed: G-FE's strict serial npm test on the head itself, and frontend-regression, with its known-debt guard, on merge commit d5d0c64b.

Final identity

  • Head: 181b76b1139d0c9c064734b940a85b865f5a15eb, tree c8e7e088d272e14debf4afa1ce272563e3acb7a3, parents ae35162b4d703e8b4ae69c9185a00d0cfe834319 and 070e7aa91c506d084a0746cbb436e5a9db0d0211.
  • Where each run executed. The push workflows, G-FE among them, ran on the head itself. The pull_request workflows ran on merge commit d5d0c64bc5d3c22f543a45640c49e52a654bd9e5, "Merge 181b76b… into 070e7aa", not on the head.
  • That merge commit, read as an object through the API: first parent 070e7aa91c506d084a0746cbb436e5a9db0d0211 (base), second parent 181b76b1139d0c9c064734b940a85b865f5a15eb (head), tree c8e7e088d272e14debf4afa1ce272563e3acb7a3, the same tree as the head. So those runs built the head's tree, on a different commit. Below, "for this head" means evidence associated with this head; the commit each job executed on is named.

CI for this head: eight runs, all success, attempt 1

Run Workflow Event Executed on
36965645361 PR regression gates, full tier, 16 jobs pull_request merge commit d5d0c64b
36965645357 Bundle validation pull_request merge commit d5d0c64b
36965645359 Lockfile drift check pull_request merge commit d5d0c64b
36965645358 Version sync check pull_request merge commit d5d0c64b
36965645318 Validate no plans path pull_request merge commit d5d0c64b
36965642157 Validate no plans path push head 181b76b1
36965642198 Validate branch name push head 181b76b1
36965642002 G-FE certification push head 181b76b1
  • 23 jobs, none failed and no job skipped. All 14 checks required on main report success for this PR head.
  • Skipped steps: two, both in issue-1850-windows-profile (release): Inventory restored gate-debug target and Upload gate-debug inventory.
  • Windows rust-regression (job 110708698205, on merge commit d5d0c64b), cargo test --locked --lib --bins --tests: lib 5841 passed; 0 failed; 26 ignored; 29 of 29 integration targets ran.
  • Ignored tests in that job's result lines: 26 in the lib suite, 5 in one integration target, 1 in another. They were not run and are not counted as passed. They are not listed by name here.
  • In that job, on merge commit d5d0c64b: T1 resolved_tao_is_at_least_0_37_1 ... ok, T2 win_harness::wm_keyup_peek_does_not_deadlock_on_reentrant_wm_killfocus ... ok, not ignored, and the coupling test tauri_crate_and_npm_api_share_a_major_minor ... ok. Windows only, one execution.
  • frontend-regression (on merge commit d5d0c64b, step npm test with #480 known-debt guard): Test Files 269 passed (269), Tests 3700 passed (3700). This is not the strict run; the strict serial npm test is G-FE's, on the head.
  • Eight runs, not ten. No push-event run of Lockfile drift check or Version sync check exists for this push. Their push triggers have path filters, and the only path this push changed, TerminalView.tsx, is in neither list. The absence is consistent with that configuration; the platform's filter decision itself was not observed. Both workflows ran on the pull_request event.

Frontend certification (G-FE) on this head

  • Run 36965642002, job 110708687792, artifact g-fe-evidence-181b76b1139d0c9c064734b940a85b865f5a15eb (ID 11209745879), ten evidence files retrieved, their nine recorded digests matched. The five command status lines each record exit 0 and the recorded installed API version is 2.12.1.
  • Owner verdict: PASS under r5 section 7 for 181b76b1139d0c9c064734b940a85b865f5a15eb, certified by the frontend owner from the ten evidence files, not from the job colour. Both tree-state logs empty; toolchain v24.13.0 and npm 11.6.2; five commands with exit 0; installed @tauri-apps/api 2.12.1; nine of nine digests matched. npm test proves mocked seams only, and the hosted read proves nothing about the user's machine or about Tauri runtime behaviour. Record: ci-181b76b1/fe-evidence-verdict.md, sha256 c7cb0c56e091919f0bfd8c5144ae65e0fbe486c42dbc03714a130c5214c99bfb.
  • That verdict is not a landing decision, not an approving review on this PR, and not causal proof.

Registered exceptions

  • Own-version exception (E-VER), this issue only. The register's words: "identity is satisfied when the only difference is the repository's own package version string, moving from 0.41.0 to 0.42.0, on the lines that carry it." Measured on this head against 1cbade7b: Cargo.lock line 13 and src-tauri/Cargo.toml line 3, one hunk each, nothing else. It is not a version bump made by this PR; the value came from main.
    • The register covers one refresh, on base d9c7db92. This head is a second refresh, on 070e7aa9, authorized separately by room 30 (route B, disposition 042207; continuation 043102). The second refresh touches none of E-VER's paths.
  • D21 exception, this issue only. check:frontend-dependencies takes its evidence from the real installed tree on the hosted runner at the assigned SHA, instead of a local run. By its registered limits it proves nothing about the user's machine or local install, and nothing about Tauri runtime behaviour.
  • Hosted route. The frontend gate is produced on a hosted runner through the carrier workflow above, not locally. It ran for this head (run 36965642002) and for the earlier heads 23c5c2ad and ae35162b. The frontend owner is the certifying owner; a green job does not certify.
  • Sequence. The commit history departs from the two planned commits. This is a recorded history exception, not a pass of that rule.

History of earlier heads, including the reds

  • 3e6992ca: coupling test negative control. It failed as designed, on an older base.
  • 23c5c2ad: ten runs, all green, including the coupling test positive control and T1, T2 on Windows.
  • ae35162b, attempt 1: PR regression gates red. One Windows unit test failed, capture::state::tests::contention_is_lock_busy_and_bounded (measured 588.4544 ms against a 250 ms limit). Its file is not touched by this change and is identical to main. Because the unit-test binary failed, the Windows integration targets did not run in that attempt.
  • ae35162b, attempt 2: one authorized rerun of that single job. Green. The coupling test, T1 and T2 executed and were ok. The red of attempt 1 remains unexplained: no cause is attributed, neither a flaky test nor a regression from this change.

All of the above names earlier SHAs. None of it is evidence for the head of this PR. In the run for this head, on merge commit d5d0c64b, that test passed, in one execution; that does not explain the earlier red.

Not run, by user disposition

Omitted under plan amendment A, on the user's instruction. These are NOT RUN, not passed:

  • G4, authority for local GUI and input work.
  • G4b, controls C1, C3a and C3b.
  • G8, Windows GUI smoke.
  • G9, the excess-send finding, as an execution item.

What this PR does not claim

  • No causal proof. No positive control was executed on the defective version. CI for this head, executed on merge commit d5d0c64b with the head's tree, shows that tao 0.37.1 resolves, builds and passes T1, T2 and the suite. It does not show by reproduction that the reported freeze was this deadlock, or that it is gone.
  • No real-runtime evidence of the new JS API minor. npm test exercises mocked seams only.
  • The excess telegram.send_message finding stays open and unexplained. No follow-up issue was filed.

Release and packaging

This PR makes no release and no version bump, and nothing was packaged or installed locally for it. CI does package: the Bundle validation workflow builds the Windows installers as part of its normal run, and did so in the run for this head (on merge commit d5d0c64b) and for the earlier heads. Those are CI build outputs, not a release.

…2817)

tao 0.34.8 held a global non-reentrant mutex while its WM_KEYUP branch
called PeekMessageW. A WM_KILLFOCUS delivered by that peek reentered the
same callback and the event-loop thread waited on itself forever.

Raise the declared tauri floor to 2.12.1, which resolves tao 0.37.1, and
add a regression test file: T1 pins the resolved tao floor, T2 drives
the reentrancy on a hidden window the test owns.
@mblua mblua added the ci:full Run the full PR regression gates on this PR label Oct 1, 2026
@socket-security

socket-security Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatedcargo/​tauri@​2.10.3 ⏵ 2.12.181100 +2100100100
Updatednpm/​@​tauri-apps/​api@​2.10.1 ⏵ 2.12.1100 +110089 +197100
Updatedcargo/​tauri-build@​2.5.6 ⏵ 2.7.19610093100100
Updatedcargo/​tao@​0.34.8 ⏵ 0.37.110010094100100

View full report

mblua added 2 commits October 1, 2026 16:30
Adds src-tauri/tests/tauri_npm_version_coupling.rs only. The test reads Cargo.lock and package-lock.json and fails when the Rust tauri crate and the npm @tauri-apps/api package differ in major.minor.

At this commit the two differ on purpose (tauri 2.12.1, @tauri-apps/api 2.10.1): this is the D15 natural negative candidate. The lockfile alignment follows in a later commit.

Refs #2817
mblua added 4 commits October 1, 2026 19:41
… tauri 2.12.1

package-lock.json: @tauri-apps/api 2.10.1 to 2.12.1, lockfile only, so the npm API shares major.minor with the Rust tauri crate. @tauri-apps/cli stays at 2.10.1.

Diagnostic fixture Cargo.lock: semver 1.0.27 to 1.0.28, so every fixture pin exists in the workspace lock.

Adds .github/workflows/g-fe-certification.yml, a single-purpose workflow that runs the five frontend certification commands on this branch.

Refs #2817
@sonarqubecloud

sonarqubecloud Bot commented Oct 2, 2026

Copy link
Copy Markdown

@mblua
mblua merged commit 147f60a into main Oct 2, 2026
27 checks passed
@mblua
mblua deleted the fix/2817-tauri-keyboard-deadlock branch October 2, 2026 13:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci:full Run the full PR regression gates on this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(windows): upgrade Tauri to prevent keyboard/focus reentry deadlock

1 participant