Skip to content

signal: remove SIGURG from default-ignore list - #2744

Open
badoriie wants to merge 1 commit into
ish-app:masterfrom
badoriie:fix/sigurg-default-ignore
Open

signal: remove SIGURG from default-ignore list#2744
badoriie wants to merge 1 commit into
ish-app:masterfrom
badoriie:fix/sigurg-default-ignore

Conversation

@badoriie

Copy link
Copy Markdown

Problem

SIGURG is currently in iSH's default-ignore list in kernel/signal.c:

case SIGURG_: case SIGCONT_: case SIGCHLD_:
case SIGIO_: case SIGWINCH_:
    return SIGNAL_IGNORE;

Go 1.14+ uses SIGURG to implement asynchronous goroutine preemption (runtime/signal_unix.go). When a Go program calls signal.Notify or the runtime installs its own SIGURG handler via runtime_sigInstall, iSH's default-ignore classification prevents proper handler registration.

The result is a hard crash on startup:

fatal: bad g in signal handler

The workaround is to set GODEBUG=asyncpreemptoff=1 before launch, which disables Go's async preemption entirely — a significant runtime regression.

Fix

Remove SIGURG_ from the ignore list. Its POSIX default disposition is already "ignored" for processes that haven't installed a handler, so removing it from this list has no effect on programs that don't use SIGURG. It only allows programs like Go to successfully install their own handler.

// Before
case SIGURG_: case SIGCONT_: case SIGCHLD_:

// After
case SIGCONT_: case SIGCHLD_:

Impact

  • Go 1.14+ programs start without GODEBUG=asyncpreemptoff=1
  • No behavioural change for programs that don't use SIGURG
  • Tested with Conduit on iSH (Alpine Linux, iPhone)

Go 1.14+ uses SIGURG to implement asynchronous goroutine preemption
(runtime/signal_unix.go). With SIGURG silently ignored, Go's runtime
cannot preempt goroutines cooperatively, leading to a 'fatal: bad g in
signal handler' crash on startup.

Removing SIGURG from the default-ignore list lets it fall through to
the default POSIX disposition (ignored for processes that haven't
installed a handler), while allowing Go's runtime_sigInstall to
register its own handler correctly.
@emkey1

emkey1 commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

I tested this one hoping to corroborate it, but the measurements point the other way, so passing them along rather than sitting on them.

Master already behaves correctly, and this patch changes it to something Linux does not do.

signal_action() checks the installed disposition before reaching that switch:

static int signal_action(struct sighand *sighand, int sig) {
    if (signal_is_blockable(sig)) {
        struct sigaction_ *action = &sighand->action[sig];
        if (action->handler == SIG_IGN_)
            return SIGNAL_IGNORE;
        if (action->handler != SIG_DFL_)
            return SIGNAL_CALL_HANDLER;    // installed handler wins here
    }
    switch (sig) {
        case SIGURG_: ... return SIGNAL_IGNORE;   // only reached for SIG_DFL

So the list only sets the default action. A process that installs a SIGURG handler — which is what the Go runtime does for async preemption — returns at SIGNAL_CALL_HANDLER and never reaches the switch.

And per signal(7), SIGURG's default action is Ign, so the entry is correct as written.

Measured with one static i386 binary run three ways — it installs a handler and raises SIGURG, then forks a child that resets to SIG_DFL and raises it again:

installed handler runs default-disposition SIGURG
real Linux yes ignored, child exits 42
upstream master yes ignored, child exits 42
master + this PR yes child killed by signal 23

Master matches Linux exactly on both. With the patch, a default-disposition SIGURG kills the process, which no Linux program expects — and it does not change the installed-handler case at all, which is the one Go depends on.

If Go's preemption really is misbehaving under iSH, the cause looks like it is somewhere else — signal delivery to a blocked thread, or restart semantics, rather than the disposition table. Happy to help chase it with the same setup if you have a Go reproducer; I have a real-Intel Linux box wired up for exactly this kind of A/B.

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.

2 participants