Skip to content

fix(input): use CFUNCTYPE to avoid variadic ABI SIGSEGV in ei_seat_bind_capabilities - #32

Open
AgainPsychoX wants to merge 2 commits into
isac322:mainfrom
AgainPsychoX:fix/libei-variadic-abi-sigsegv
Open

fix(input): use CFUNCTYPE to avoid variadic ABI SIGSEGV in ei_seat_bind_capabilities#32
AgainPsychoX wants to merge 2 commits into
isac322:mainfrom
AgainPsychoX:fix/libei-variadic-abi-sigsegv

Conversation

@AgainPsychoX

@AgainPsychoX AgainPsychoX commented Jun 2, 2026

Copy link
Copy Markdown

Problem

session_connect crashes with SIGSEGV inside ei_seat_bind_capabilities on Python 3.14 + libei 1.5.0 (reported in #29 for Fedora 43 / Bazzite).

Root cause: the original code called ei_seat_bind_capabilities as a raw ctypes variadic function. Raw variadic calls via ctypes/libffi are ABI-fragile — on Python 3.14 the register/stack placement is wrong, causing a crash inside the C function.

A secondary bug: the sentinel was c_void_p(None) (NULL pointer), but libei's loop terminator is while ((cap = va_arg(args, enum ei_device_capability)) > 0) — it checks cap > 0, not a pointer-NULL. The correct sentinel is c_int(0).

Fix

Build a fully-typed ctypes.CFUNCTYPE for the exact argument list (seat pointer + N capability uints + int sentinel). This gives libffi explicit register/stack placement for every argument, eliminating the ABI ambiguity regardless of Python or libffi version.

FuncType = ctypes.CFUNCTYPE(
    None,
    ctypes.c_void_p,                     # seat
    *([ctypes.c_uint] * len(bind_list)), # capabilities
    ctypes.c_int,                        # sentinel 0
)
FuncType(_libei.ei_seat_bind_capabilities)(seat, *bind_list, 0)

Testing

Tested on Manjaro (libei 1.4.x) via both the CLI (uv run python -m kwin_mcp.cli) and live MCP session — no regression, session_connect succeeds and input injection works correctly.


🤖 This issue was analysed, fixed, and verified end-to-end using Claude Code (claude-sonnet-4-6) running kwin-mcp as a live MCP server — the fix was tested by actually connecting a session through the patched code.

Fixes #29

Patryk Ludwikowski and others added 2 commits June 2, 2026 13:38
…_capabilities

Raw ctypes variadic calls are ABI-fragile across Python/libffi versions.
On Python 3.14 + libei 1.5.0 the wrong register/stack placement causes
a SIGSEGV inside ei_seat_bind_capabilities. Building a fully-typed
CFUNCTYPE for the exact argument list gives libffi explicit placement.

Also fixes the sentinel: the loop terminates on `cap > 0`, so the
terminator must be c_int(0), not c_void_p(None).

Fixes isac322#29

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The previous commit used c_int(0); the public API documents the
sentinel as NULL. Switch to c_void_p(None) to match the contract.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.

session_connect segfaults in ei_seat_bind_capabilities on libei 1.5.0 (Fedora 43 / Bazzite)

1 participant