signal: replace raise(SIGUSR1) with self-pipe to fix SIGABRT on glibc >= 2.42#658
Merged
Conversation
|
Ephemeral COPR build failed. @containers/packit-build please check. |
50a4d4f to
4c0e851
Compare
giuseppe
approved these changes
May 18, 2026
Member
giuseppe
left a comment
There was a problem hiding this comment.
LGTM after the CI failure is addressed
… >= 2.42
When on_sig_exit() cannot forward a signal to the container process
(kill() fails), it needs to wake the GLib main loop to force a
child-process check. Previously this was done via raise(SIGUSR1),
relying on the fact that SIGUSR1 is blocked and coalesced by signalfd.
On glibc >= 2.42, calling raise() from a signal handler while the main
thread is in ppoll() triggers glibc's __syscall_cancel mechanism:
ppoll() detects that a signal was raised for the current thread and
aborts with SIGABRT.
Fix: replace raise(SIGUSR1) with the self-pipe trick:
- Create a pipe2(O_CLOEXEC | O_NONBLOCK) during startup.
- Register a GLib IO source on the read end that drains bytes and
triggers check_child_processes().
- In on_sig_exit(), write one byte to the write end instead of
calling raise(). This is async-signal-safe (POSIX section 2.4.3).
- errno is preserved around the write() in self_pipe_wake().
Extract the logic into a reusable self_pipe.h/self_pipe.c module so
that any future signal handler can use self_pipe_wake() without
duplicating pipe setup code. Add self_pipe_fini() for proper cleanup
on exit (g_source_remove + close both ends).
Fixes: #657
Signed-off-by: Jindrich Novy <jnovy@redhat.com>
4c0e851 to
bafb655
Compare
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.
Problem
When
on_sig_exit()cannot forward a signal (SIGTERM/SIGQUIT/SIGINT) to the container process becausekill()fails, it needs to wake the GLib main loop. Previously this was done viaraise(SIGUSR1).On glibc >= 2.42, calling
raise()from a signal handler while the main thread is inppoll()triggers glibc's__syscall_cancelmechanism, causing conmon to abort with SIGABRT.Fix
Replace
raise(SIGUSR1)with the self-pipe trick — an async-signal-safe pattern:raise()check_child_processes()The self-pipe logic is extracted into a reusable module (
src/self_pipe.h/src/self_pipe.c) withself_pipe_init(),self_pipe_wake(), andself_pipe_fini(). This makes it available for any future signal handler that needs to wake the main loop safely.Fixes: #657