fix: declare Win32 signatures to avoid 64-bit handle truncation#698
Merged
Conversation
… truncation ctypes defaults function restype/argtypes to 32-bit c_int, so the HANDLE returned by CreateMutexW and the HWNDs from FindWindowW were truncated on 64-bit Windows before being passed back to CloseHandle/ShowWindow/ SetForegroundWindow. Declare c_void_p signatures for the kernel32 and user32 calls so handles round-trip intact. Signature setup is suppressed on the test fakes (plain methods reject attribute assignment), so behavior is unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Same 64-bit handle-truncation issue as the single-instance mutex fix: the HWND from frame.GetHandle() was passed to IsIconic/ShowWindow/ SetForegroundWindow through ctypes' default c_int restype/argtypes, truncating the pointer on 64-bit Windows. Use a local WinDLL with declared c_void_p signatures (rather than the shared ctypes.windll cache) so the handle round- trips intact without mutating process-global function prototypes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This was referenced May 28, 2026
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drives _force_foreground_window through fake user32/kernel32 DLLs so the handle-signature path is exercised on non-Windows CI, plus a non-Windows case asserting the frame.Raise() fallback. Satisfies the diff-coverage gate for the rewritten ctypes block. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Orinks
added a commit
that referenced
this pull request
May 28, 2026
…ling (#699) > **Stacked on #698** (base is `fix/single-instance-handle-truncation`, not `dev`). Retarget to `dev` after #698 merges. Follow-up cleanup to the single-instance activation path. No relation to the ABI fix in #698 beyond touching the same files — kept separate so each PR has one thesis. ## Changes 1. **Dedupe the fallback handoff (correctness).** When the named-pipe IPC is unavailable, `request_existing_instance_show` used to *both* write the handoff file *and* poke the window directly — so the primary instance could act on the same request twice (once via the handoff poll, once via the direct restore). Now the handoff is skipped for a plain `generic_fallback` that a successful window restore already satisfied, while `discussion`/`alert_details` intents — which the window poke can't carry — are still handed off. Window-restore logic extracted into `_show_existing_window`. 2. **Relax the handoff poll 750ms → 2000ms** via a named constant. The file handoff is only a fallback to IPC, so it doesn't need sub-second latency and shouldn't run a perpetual high-frequency timer for the whole session. 3. **Document the "allow startup on any failure" policy** in `try_acquire_lock`. ## Tests Two new tests assert the dedupe: generic-on-success writes no handoff; `discussion`-on-success still does. 32/32 single-instance + activation tests pass. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Declares explicit
ctypesrestype/argtypesfor the Win32 calls in the single-instance startup path and in_force_foreground_window.Why
ctypesdefaults a function'srestype/argtypesto 32-bitc_int. On 64-bit Windows aHANDLE/HWNDis pointer-width, so handles were being silently truncated before being passed back toCloseHandle/ShowWindow/SetForegroundWindow. It usually works only because handles often happen to fit in the low 32 bits — exactly the kind of latent bug that surfaces intermittently in the field and never in tests (the test fakes return plain ints and can't exercise the real ctypes ABI).Changes
single_instance.py:CreateMutexW/CloseHandle(kernel32) andFindWindowW/EnumWindows/GetWindowText*/ShowWindow/SetForegroundWindow(user32) now declarec_void_psignatures. Setup is wrapped incontextlib.suppressso the test fakes (plain methods, which reject attribute assignment) keep working unchanged.app_activation.py:_force_foreground_windowuses a localWinDLLwith declared signatures instead of the sharedctypes.windllcache, so the fix doesn't mutate process-global prototypes.Behavior
No behavior change on the happy path — handles simply round-trip intact. All existing single-instance and activation tests pass (30/30).
🤖 Generated with Claude Code