← board

riscv32: SA_ONSTACK is registered but has no effect under qemu

Residue from [[bug-a-four-hosted-targets-install-signal-handlers-without-an-altstack]], which fixed i386, arm32 and aarch64. riscv32 got the same treatment and is the one target where it does not take.

Measured (2026-08-21, qemu 10.2.1, Debian 1:10.2.1+ds-1ubuntu3.1)

A handler that does nothing but Halt(9), installed for SIGSEGV, against an unbounded recursion:

target exit
i386 9 (handler ran)
arm32 9
aarch64 9
riscv32 139 (killed; handler never entered)

And with an ordinary nil deref — a fault that leaves plenty of stack, so the handler runs everywhere — printing where the handler's own frame lives:

target handler frame main's frame
i386 134636076 (the BSS alt stack) 134642064
arm32 134759292 (BSS) 134764944
aarch64 4364316 (BSS) 4373824
riscv32 724215292 — 0x2AAAB..., the guest STACK 134784528 (BSS)

So on riscv32 the handler runs on the normal stack even for a fault that has nothing to do with stack space. SA_ONSTACK is simply not being honoured.

Our side is correct, and that is verified rather than assumed

What is left to establish

The remaining variable is qemu-user's riscv signal-frame setup — whether it picks the frame address with target_sigsp() (which honours SA_ONSTACK) or straight from the CPU state. Same qemu build honours it on i386, arm and aarch64, so this is riscv-specific there or riscv-specific here, and the measurements above do not separate those two.

It cannot be settled on this box: there is no RISC-V hardware and no second riscv emulator here. Settle it by (a) reading qemu's linux-user/riscv/signal.c for the release in use, or (b) running the probe on real RV hardware. Until then the registration stays — it is correct code asking for correct behaviour, not a workaround, and it will start working the moment the other side does.

Consequence today

test_stack_overflow_raise runs on four of five hosted targets. riscv32 is excluded there with this ticket named, not silently skipped. Ordinary signal handling on riscv32 is unaffected — only a fault that exhausts the stack is unhandleable, which is exactly the case the alt stack exists for.

Gate

The Halt(9) probe exiting 9 under riscv32, and test_stack_overflow_raise promoted to all five targets.