fix(kvm): stop SIGBUS core dump in PipeWire screencast teardown #103

Merged
Claude-Run merged 1 commit from fix/VA-92-pipewire-teardown-sigbus into main 2026-07-03 17:10:19 +02:00
Member

The Wayland dlopen PipeWire consumer read through an mmap'd compositor buffer (portal.rs on_process) with only null and offset/size-vs-maxsize guards. On agent or graphical-session restart the compositor tears down the ScreenCast stream and truncates the memfd backing the buffer while the consumer thread is mid-read; the pointer stays non-null and the offsets stay in-bounds, only the pages become inaccessible, so the read faults with SIGBUS (signal 7) and dumps core.

Fix the teardown race and make any residual fault diagnosable:

Diagnosability. Retain line-table debuginfo plus the ELF symbol table in the release profile (debug = "line-tables-only", drop strip = "symbols") so a captured core resolves frames instead of the single useless frame a stripped build produced. Install a SIGBUS/SIGSEGV sigaction handler (vervain_agent::crashlog) that writes a resolvable backtrace to stderr, then restores the default disposition and re-raises so the kernel still dumps core.

Teardown race. Wire state_changed into STREAM_EVENTS and track a streaming AtomicBool in CallbackData; on_process now returns early unless the stream is Streaming, so it never reads a buffer whose memfd the server has reclaimed. Wire remove_buffer (the consumer holds no cross-callback buffer reference, so there is nothing to drop, but the slot is now observed). Replace the leaked "runs forever" consumer with a stored ConsumerHandle: the loop's pw_main_loop pointer is sent back to the spawner, agent shutdown calls pw_main_loop_quit (an eventfd signal, safe cross-thread) to wake pw_main_loop_run, and the thread then disconnects and destroys the stream/context/loop and frees the callback box before exiting. main.rs calls portal::shutdown_blocking() on the shutdown path so a systemctl restart tears the stream down cleanly.

Bind the pw_main_loop_quit / pw_main_loop_destroy / pw_context_destroy / pw_stream_disconnect / pw_stream_destroy symbols in pw_ffi to support the clean stop.

#VA-92

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

The Wayland dlopen PipeWire consumer read through an mmap'd compositor buffer (portal.rs on_process) with only null and offset/size-vs-maxsize guards. On agent or graphical-session restart the compositor tears down the ScreenCast stream and truncates the memfd backing the buffer while the consumer thread is mid-read; the pointer stays non-null and the offsets stay in-bounds, only the pages become inaccessible, so the read faults with SIGBUS (signal 7) and dumps core. Fix the teardown race and make any residual fault diagnosable: Diagnosability. Retain line-table debuginfo plus the ELF symbol table in the release profile (debug = "line-tables-only", drop strip = "symbols") so a captured core resolves frames instead of the single useless frame a stripped build produced. Install a SIGBUS/SIGSEGV sigaction handler (vervain_agent::crashlog) that writes a resolvable backtrace to stderr, then restores the default disposition and re-raises so the kernel still dumps core. Teardown race. Wire state_changed into STREAM_EVENTS and track a streaming AtomicBool in CallbackData; on_process now returns early unless the stream is Streaming, so it never reads a buffer whose memfd the server has reclaimed. Wire remove_buffer (the consumer holds no cross-callback buffer reference, so there is nothing to drop, but the slot is now observed). Replace the leaked "runs forever" consumer with a stored ConsumerHandle: the loop's pw_main_loop pointer is sent back to the spawner, agent shutdown calls pw_main_loop_quit (an eventfd signal, safe cross-thread) to wake pw_main_loop_run, and the thread then disconnects and destroys the stream/context/loop and frees the callback box before exiting. main.rs calls portal::shutdown_blocking() on the shutdown path so a systemctl restart tears the stream down cleanly. Bind the pw_main_loop_quit / pw_main_loop_destroy / pw_context_destroy / pw_stream_disconnect / pw_stream_destroy symbols in pw_ffi to support the clean stop. #VA-92 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
fix(kvm): stop SIGBUS core dump in PipeWire screencast teardown
All checks were successful
Check / fmt + clippy + tests (pull_request) Successful in 11m23s
Create release / Create release from merged PR (pull_request) Has been skipped
d5443dc602
The Wayland dlopen PipeWire consumer read through an mmap'd compositor buffer (portal.rs on_process) with only null and offset/size-vs-maxsize guards. On agent or graphical-session restart the compositor tears down the ScreenCast stream and truncates the memfd backing the buffer while the consumer thread is mid-read; the pointer stays non-null and the offsets stay in-bounds, only the pages become inaccessible, so the read faults with SIGBUS (signal 7) and dumps core.

Fix the teardown race and make any residual fault diagnosable:

Diagnosability. Retain line-table debuginfo plus the ELF symbol table in the release profile (debug = "line-tables-only", drop strip = "symbols") so a captured core resolves frames instead of the single useless frame a stripped build produced. Install a SIGBUS/SIGSEGV sigaction handler (vervain_agent::crashlog) that writes a resolvable backtrace to stderr, then restores the default disposition and re-raises so the kernel still dumps core.

Teardown race. Wire state_changed into STREAM_EVENTS and track a streaming AtomicBool in CallbackData; on_process now returns early unless the stream is Streaming, so it never reads a buffer whose memfd the server has reclaimed. Wire remove_buffer (the consumer holds no cross-callback buffer reference, so there is nothing to drop, but the slot is now observed). Replace the leaked "runs forever" consumer with a stored ConsumerHandle: the loop's pw_main_loop pointer is sent back to the spawner, agent shutdown calls pw_main_loop_quit (an eventfd signal, safe cross-thread) to wake pw_main_loop_run, and the thread then disconnects and destroys the stream/context/loop and frees the callback box before exiting. main.rs calls portal::shutdown_blocking() on the shutdown path so a systemctl restart tears the stream down cleanly.

Bind the pw_main_loop_quit / pw_main_loop_destroy / pw_context_destroy / pw_stream_disconnect / pw_stream_destroy symbols in pw_ffi to support the clean stop.

#VA-92

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Run deleted branch fix/VA-92-pipewire-teardown-sigbus 2026-07-03 17:10:19 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/vervain-agent!103
No description provided.