alexcrichton opened issue #10000:
I've seen two CI builds fail today on the s390x tests of the
wasmtime-clicrate:
- https://github.com/bytecodealliance/wasmtime/actions/runs/12752790805/job/35543074991 (https://github.com/bytecodealliance/wasmtime/pull/9982#event-15909676078)
- https://github.com/bytecodealliance/wasmtime/actions/runs/12755184456/job/35550742014 (https://github.com/bytecodealliance/wasmtime/pull/9994#event-15912281849)
The first was re-queued and merged and the second is currently back in the queue. The first didn't touch anything in
wasmtime-cliand the second does touch quite a bit that could affect it so it's currently an assumption of mine that the s390x-failure there was specific to s390x.I tried running the test suite in a loop locally for a bit using s390x/qemu and so far it hasn't failed in the same way. I figured I'd open an issue to keep track of things if they happen in the future.
cc @uweigand
iii-i commented on issue #10000:
In my local runs I've seen segfaults due to an ABI problem in the capstone wrapper: https://github.com/capstone-rust/capstone-rs/pull/166. I wonder if this can be related?
abrown added the cranelift:area:s390x label to Issue #10000.
abrown commented on issue #10000:
Not sure, but I believe I saw a similar failure over in #10110: https://github.com/bytecodealliance/wasmtime/actions/runs/13124822832/job/36618948362#step:18:987.
alexcrichton commented on issue #10000:
Another failure at https://github.com/bytecodealliance/wasmtime/actions/runs/13421426149/job/37494891337
alexcrichton commented on issue #10000:
alexcrichton commented on issue #10000:
alexcrichton added the ci label to Issue #10000.
alexcrichton commented on issue #10000:
alexcrichton commented on issue #10000:
alexcrichton commented on issue #10000:
alexcrichton commented on issue #10000:
uweigand commented on issue #10000:
Hi @alexcrichton , these seems to be qemu - are we now running CI on qemu again vs. the native GitHub actions? Just wondering whether you've seen any of these segfaults on native as well ...
These qemu failures are hard to reproduce - can we at least try to capture core dumps?
alexcrichton commented on issue #10000:
Yeah I believe these are all through QEMU, not native. After the incident awhile back we switched back to QEMU and haven't gone back to native after that so far.
I'd capture core dumps if I knew how to, but I'm not sure how to capture/upload core dumps from github actions :(
I mostly just want to be sure to log these over time to track incident rate, no need to urgently fix or such.
alexcrichton commented on issue #10000:
alexcrichton commented on issue #10000:
alexcrichton commented on issue #10000:
fitzgen commented on issue #10000:
alexcrichton commented on issue #10000:
@uweigand if you're interested and have some spare cycles, I pointed an LLM at this in the hopes that it might be able to find something and it ... sort of did. I've attached 3 different core files here I captured locally as well as the LLM summary. No real progress was made in creating a reproduction and it still takes ~20 minutes to reproduce locally with very heavy load. I was able to reproduce with the tip-of-tree QEMU in addition to the one we're using in CI to at least verify that this hasn't been fixed in the meantime.
I realize that this is a big dump of info and you're by no means obligated to sift through it. The current conclusion is that this is related to signal handlers so I'm going to go and try to disable signal handlers in CI for s390x and see if that helps. Unfortunately not much else is actionable at this time AFAIK -- I can't really make heads or tails of this summary myself. Without a standalone reproducer it's very difficult to reason about.
core-C-qemu-master-11.0.50-not-fixed.core.gz
uweigand commented on issue #10000:
@uweigand if you're interested and have some spare cycles, I pointed an LLM at this in the hopes that it might be able to find something and it ... sort of did.
Well, this is interesting. The report itself appears to simply conclude that if QEMU were to randomly corrupt guest register values, then that could explain the crashes ... which is true but not particularly helpful. I couldn't find any specific clue as to where and why such corruption might happen.
However, the good news is that there at least appears to be a somewhat reliable reproducer. That in itself would be quite helpful and allow me to start having a look. Do you have the scripts to reproduce - according to REPORT.md they're supposed to be in the
reproducers/andtools/directories? If not, I guess I can build my own.
alexcrichton commented on issue #10000:
The reproduction is effectively
cargo test --test wastin a loop. CI has some settings to mirror (e.g. opt-level=2, no incremental, etc), and there's some bits about basically running a bunch of them to try to get more interesting scheduler interleavings. It still took 10-30 minutes to reproduce, however, so knowing whether something is fixed or not is unfortunately not easy.
alexcrichton commented on issue #10000:
The hack added in #13537 didn't work as surfaced through failures on https://github.com/bytecodealliance/wasmtime/pull/13613. Reverting that in https://github.com/bytecodealliance/wasmtime/pull/13618.
alexcrichton commented on issue #10000:
@uweigand would you be able to help hunt this down in a possibly architecture-agnostic area of QEMU? We got a different failure today which while on s390x doesn't seem to be s390x-specific. Specifically this program seems to either reproduce the CI failure or indicate something separate. Namely this reads into a guaranteed-valid buffer and gets
EFAULTfrom qemu-user. If you're not otherwise already familiar with qemu or don't have prior experience I can also try reporting this upstream to them as well.
uweigand commented on issue #10000:
@uweigand would you be able to help hunt this down in a possibly architecture-agnostic area of QEMU? We got a different failure today which while on s390x doesn't seem to be s390x-specific. Specifically this program seems to either reproduce the CI failure or indicate something separate. Namely this reads into a guaranteed-valid buffer and gets
EFAULTfrom qemu-user. If you're not otherwise already familiar with qemu or don't have prior experience I can also try reporting this upstream to them as well.Hi @alexcrichton , I've tried to reproduce this but without success so far. Can you share more data about your host environment (host architecture, OS/distro, qemu version, kernel version)?
In general, I'd be happy to have a look. But given that it seems to be a general problem it would of course also be good to report upstream.
alexcrichton commented on issue #10000:
I'm on x86_64 Linux with 7.0.0-22-generic and Ubuntu 26.04 using
qemu-aarch64 version 9.1.2as a reproduction personally.
uweigand commented on issue #10000:
OK, I was able to reproduce in that environment, but it still takes multiple iterations of the test. It does occur every 5 minutes or so. I've also been able to reproduce on Ubuntu 24.04 and with various qemu versions.
However, this was all on x86_64 Linux as host. On s390x Linux as host I have not been able to reproduce the problem at all.
@iii-i you mentioned you were seeing a similar issue in the past. Can you have a look at the mmrace.c test case linked above (https://github.com/bytecodealliance/wasmtime/issues/10000#issuecomment-4714102951) and verify that this is the same problem?
iii-i commented on issue #10000:
I wrote something similar a few years back; shortly thereafter it started failing spuriously in CI and was disabled; unfortunately nobody had the time to investigate.
This seems to be a race between lockless reads in
page_check_range()andpageflags_set_clear(). I have a dirty fix now and will try to make something upstreamable out of it.
uweigand commented on issue #10000:
The reproduction is effectively
cargo test --test wastin a loop. CI has some settings to mirror (e.g. opt-level=2, no incremental, etc), and there's some bits about basically running a bunch of them to try to get more interesting scheduler interleavings. It still took 10-30 minutes to reproduce, however, so knowing whether something is fixed or not is unfortunately not easy.Getting back to the s390x specific failure, I've tried to reproduce it like you describe here, but without success even after running many hours. Either I'm doing something wrong or the timing behavior of my system is just different ...
Is there any way to extract core file plus associated executable from one of the crashes you were seeing? Maybe that would at least allow me to seeing something ...
alexcrichton commented on issue #10000:
IIRC it also took ~hours to reproduce locally and also required a ton of load/tuning to get something to reproduce due to what I presume being a really small race window. I don't have cores/executables on-hand myself, but I can try to poke a bit more once the fix for the other issue lands. I'll attempt to re-enable signals on CI and see if we got lucky and it's the same issue or if there's a second one
uweigand commented on issue #10000:
@uweigand if you're interested and have some spare cycles, I pointed an LLM at this in the hopes that it might be able to find something and it ... sort of did.
Well, this is interesting. The report itself appears to simply conclude that if QEMU were to randomly corrupt guest register values, then that could explain the crashes ... which is true but not particularly helpful. I couldn't find any specific clue as to where and why such corruption might happen.
Since I'm still unable to reproduce on my own, I went back to this and tried to extract as much info as possible from just the core files without the associated executable. At least I was able to confirm that the "randomly corrupt guest register values" theory is definitely incorrect. The AI report states:
Crashing thread PC in JIT code at
l %r3,16(%r2)withr2 = 0→ load from0x10→ SIGSEGV. Preceding instructions:
lg %r3,0(%r3) ; r3 = pointer lgr %r2,%r3 ; r2 = r3 nill %r2,65534 ; r2 &= ~1 (r3 = 0x…f8c8 is even -> no-op) cghi %r3,0 / jgnlh ; null-check r3 (non-null -> fall through) l %r3,16(%r2) ; FAULT, r2 == 0At the fault
r3 = 0x…f8c8(even), sor2must equalr3(a live, mapped pointer) — butr2 = 0. Nothing rewritesr2between its assignment and the load. On a correct CPU the load would succeed; the fault exists only because a guest register was spuriously zeroed. (This is the rarer signature.)But this overlooks the fact that there is a second control flow path via a branch into the faulting
l %r3,16(%r2)instruction, wherer2can actually be legitimately zero. This code sequence was generated fromtable_get_funcref, which has a cold path calling into thetable_get_lazy_init_func_ref, which may return NULL.Therefore, the
l %r3,16(%r2)is supposed to be marked with a TRAP_INDIRECT_CALL_TO_NULL marker, and the SIGSEGV should be handled that way - but it isn't.This now actually matches the second example in the AI report, where we also have a SIGSEGV on an instruction that is properly marked as potentially trapping, so this could very well be the same underlying root cause. I have not been able to track this down so far, unfortunately.
Last updated: Jul 29 2026 at 05:03 UTC