Skip to content

Fix v1.26 crashes: emutls corruption#132

Merged
ChristopherHX merged 11 commits intominecraft-linux:masterfrom
trasnake87:v1.26-crash-fixes
Feb 13, 2026
Merged

Fix v1.26 crashes: emutls corruption#132
ChristopherHX merged 11 commits intominecraft-linux:masterfrom
trasnake87:v1.26-crash-fixes

Conversation

@trasnake87
Copy link
Contributor

@trasnake87 trasnake87 commented Feb 12, 2026

Summary

Fixes three crash/shutdown issues when running Minecraft Bedrock v1.26.0.2:

  • (REMOVED) Immediate shutdown after ~3 seconds: Minecraft v1.26 calls GameActivity_finish() during startup as part of the Android activity lifecycle transition. The launcher was treating this as a real exit request. Fixed by making onGameActivityClose a no-op since window close already handles clean shutdown.

  • SIGABRT on startup from corrupted emutls: The v1.26 libminecraftpe.so has a corrupted __emutls_control struct at base+0x13701258 where emutls data overlaps with rand_meth symbol data due to linker symbol collisions. Fixed by patching the corrupted control to valid values after library load.

  • (REMOVED) SIGSEGV on keyboard input and world creation: Two crash sites in libminecraftpe.so that can be safely recovered from via signal handler:

    1. mc+0x9dc22fd: Table lookup with out-of-bounds index triggered by keyboard input (arrow keys). Sets null string values and lets the function's built-in null-check path handle recovery.
    2. mc+0xcbe8f40: URL decode with invalid string pointer. Unwinds the function prologue and returns 0 (no match).

    Unknown crashes are logged with register state and instruction bytes for diagnosis, then re-raised with default behavior.

Testing

Tested on Pop!_OS 22.04 (x86_64) with Minecraft Bedrock v1.26.0.2 via Flatpak. All three issues are resolved - the game launches, signs into Xbox Live, creates/loads worlds, and handles keyboard input without crashing.

Notes

This PR builds on top of #131 (1.26.0 fixes by GameParrot). The three commits are independent fixes that can be reviewed/cherry-picked separately.

GameParrot and others added 7 commits January 26, 2026 12:29
Minecraft v1.26 calls GameActivity_finish() during startup as part of
the Android activity lifecycle transition (switching from the splash
activity to the game activity). The launcher was incorrectly treating
this as a real exit request, causing the game to shut down within ~3
seconds of launch with "The graphics context was lost".

Make onGameActivityClose a no-op since the window close event already
handles clean shutdown via WindowCallbacks::onClose().
The v1.26 libminecraftpe.so binary has a corrupted __emutls_control
struct at base+0x13701258 where the emutls data overlaps with
rand_meth symbol data due to linker symbol collisions. This causes
SIGABRT when TLS variables are accessed during startup.

Patch the corrupted control to valid values {size=8, align=8, index=0,
templ=NULL} after the library is loaded.
The v1.26 libminecraftpe.so has two known crash sites that can be
safely recovered from using a signal handler:

1. mc+0x9dc22fd: Table lookup with out-of-bounds index triggered by
   keyboard input (e.g. arrow keys). The function loads a string
   pointer/length pair from a global table indexed by edx*16 without
   bounds checking. Recovery: set r14=r15=0 (null string) and skip to
   mc+0x9dc2306, letting the function's built-in null check handle it.

2. mc+0xcbe8f40: URL decode function crashes on invalid string pointer.
   Recovery: unwind the function prologue and return 0 (no match).

Unknown SIGSEGV crashes are logged with register state and instruction
bytes for diagnosis, then re-raised with default behavior.
@ChristopherHX
Copy link
Member

Sounds interesting, thank you (but I didn't yet come to the point for evaluating this patchset)

  • We have already crash handler in mcpelauncher-core, so I prefer to place this there.
  • Your code needs to query the Minecraft Version before applying any patch that are version specific
    • Use MinecraftVersion from mcpelauncher-core the mcpelauncher-client should assign valid values as of recently again.
  • Is the linux check even necessary? all x86_64 platform have the same offsets for the same binary, since they are from android. Except if the crash handler interface is incompatible then it makes sense.

Fix corrupted emutls control struct causing SIGABRT on v1.26

Now I wonder could we reimplement emutls that it automatically detects corruption, since this is a common problem we face for x86_64 builds not only once.

@ChristopherHX
Copy link
Member

  • Immediate shutdown after ~3 seconds: Minecraft v1.26 calls GameActivity_finish() during startup as part of the Android activity lifecycle transition. The launcher was treating this as a real exit request. Fixed by making onGameActivityClose a no-op since window close already handles clean shutdown.

This breaks closing the game for me, but actually I think by lib folder contains except libminecraftpe.so shared libs from 26.0.27 x86_64.


But Thank you very much 26.0 x86_64 is playable with your patchset

@ChristopherHX
Copy link
Member

SIGSEGV on keyboard input and world creation: Two crash sites in libminecraftpe.so that can be safely recovered from via signal handler:

  1. mc+0x9dc22fd: Table lookup with out-of-bounds index triggered by keyboard input (arrow keys). Sets null string values and lets the function's built-in null-check path handle recovery.
  2. mc+0xcbe8f40: URL decode with invalid string pointer. Unwinds the function prologue and returns 0 (no match).

Unknown crashes are logged with register state and instruction bytes for diagnosis, then re-raised with default behavior.

Couldn't repro this yet, will rollback by .so files to the apk version..., and try again

@ChristopherHX
Copy link
Member

I am going to pick at least

  • 96ec8b0
  • with my change to only apply it for a single version: b0940d4 on x86_64

@ChristopherHX
Copy link
Member

CC @GameParrot What do you think? The game activity close patch causes more issues than it solves for me, the segv handler patch never got called on my end.

Tested with the 26.0.2 x86_64 apk and the replaced prefabmultiplayer .so file.

@trasnake87
Copy link
Contributor Author

Thanks for the detailed feedback and for pushing the version-scoping commit!

A few responses:

Re: __linux__ guard — You're right that the binary offsets are the same regardless of host platform. The guard is purely about the signal handler API: macOS uses uc->uc_mcontext->__ss.__rip (pointer, different struct) vs Linux's uc->uc_mcontext.gregs[REG_RIP], and 32-bit Linux uses REG_EIP/REG_ESP instead of REG_RIP/REG_RSP. So it's an API compat thing, not an offset thing.

Re: GameActivity_finish — Sorry about that. The immediate shutdown I was hitting was specifically on 1.26.0.2 x86_64 where GameActivity_finish gets called ~3 seconds after launch during what looks like a lifecycle transition. Making it a full no-op is clearly too aggressive if it breaks normal exit on other versions. A better approach would be to either scope it with MinecraftVersion or only ignore the first call (before the game is fully initialized). Happy to rework this.

Re: SIGSEGV handler — This only triggers with the specific 1.26.0.2 x86_64 binary at exact offsets. If you're using .so files from a different version the offsets would be different, so the handler would never match (and would fall through to the default abort path). Makes sense you couldn't repro with mixed libs.

Re: moving to mcpelauncher-core — Agreed, that's a better home for it. I can rebase it there if you'd like, or feel free to cherry-pick and restructure however works best for the project.

Re: auto-detecting emutls corruption — That would be a much cleaner long-term solution. The pattern is pretty detectable: valid controls should have reasonable size/align values (typically 4 or 8) and templ should either be NULL or point within the binary. Anything with garbage values in those fields is corrupt.

@sigkacey
Copy link

  • Immediate shutdown after ~3 seconds: Minecraft v1.26 calls GameActivity_finish() during startup as part of the Android activity lifecycle transition. The launcher was treating this as a real exit request. Fixed by making onGameActivityClose a no-op since window close already handles clean shutdown.

This breaks closing the game for me, but actually I think by lib folder contains except libminecraftpe.so shared libs from 26.0.27 x86_64.

But Thank you very much 26.0 x86_64 is playable with your patchset

I have it fully playable with the patchset too, stable also. Does break game closing for me also though, need some form of termination either with a kill or closing the launcher and having it do the prompted force kill it offers. Today was my first build of this from source some I'm not mega sure I haven't got crossover on libs from the .deb install and flatpack install I also have

Good stuff :-)

@ChristopherHX
Copy link
Member

This specific crash can also be mitigated by this code that has no hardcoded offsets.

  • The reset of ctrl->templ should be guarded by a elf segment test towards rodata to be preserved.
  • ctrl->index seems to be incremented by runtime, if this has not been assigned by a __emutls_get_address call this number is invalid.
  • ctrl->size looks like a guessing game
    struct EmutlsControl {
        size_t size;
        size_t align;
        uintptr_t index;
        void* templ;
    };
    static mcpelauncher_hook_t val;
    val.value = linker::dlsym(libcxx, "__emutls_get_address");
    static mcpelauncher_hook_t* org = &val;
    hooks.emplace_back(mcpelauncher_hook_t{"__emutls_get_address", (void*)+[](EmutlsControl* ctrl) {
        double scratch;
        if(modf(log2(ctrl->align), &scratch) != 0.0) {
            Log::error("MinecraftUtils", "Unsupported emutls alignment %zu", ctrl->align);
            ctrl->size = 64;
            ctrl->align = 8;
            ctrl->index = 0;
            ctrl->templ = nullptr;
        }
        return ((void*(*)(EmutlsControl* ctrl))org->value)(ctrl);
    }});

I will still do revert pushes here like explained in #132 (comment), plz create a new PR for the changes I could not validate yet. Maybe then target another repository directly.

Thank you for trying your luck yourself, the last time some versions behind I probably did interpret the emutl struct wrongly to correct the crash.

@ChristopherHX ChristopherHX changed the title Fix v1.26 crashes: GameActivity lifecycle, emutls corruption, SIGSEGV recovery Fix v1.26 crashes: emutls corruption Feb 13, 2026
@ChristopherHX ChristopherHX merged commit 0701f19 into minecraft-linux:master Feb 13, 2026
15 of 19 checks passed
@ChristopherHX
Copy link
Member

One follow up is minecraft-linux/mcpelauncher-core#22 that I keep open for further research.

@trasnake87
Copy link
Contributor Author

Sorry about the GameActivity_finish issue — I got the game running for the first time and immediately started playing with my kids rather than testing the close button properly.

I've reworked the patch based on your feedback:

  • GameActivity_finish: Instead of a full no-op, it now ignores only the first call (the startup lifecycle transition) and honors subsequent calls so the in-game quit button works normally.
  • Window close (X button): Added requestExitGame() to the window close handler since nativeShutdown alone doesn't trigger the exit flow for GameActivity versions. Both the X button and in-game quit now shut down cleanly.

Tested both close paths — X button and in-game "Save and Quit" both work correctly.

The commits are reorganized as 4 independent patches now:

  1. e39703c — GameActivity_finish startup fix
  2. c3f9152 — Window close requestExitGame for GameActivity
  3. 45ae7be — emutls control corruption fix
  4. add814e — SIGSEGV recovery handler (x86_64 Linux only)

@ChristopherHX
Copy link
Member

ChristopherHX commented Feb 13, 2026

I merged

3. 45ae7be — emutls control corruption fix

so this PR is closed as merged.

I am not yet convinced by the other 3, since they appear to not affect me...

The patches 1&2 might be interesting for me to validate on macOS 26.0 arm64, where I saw a 80% reproductive game close with exit code 0

Does this sound like your observed problem?

I released the merged change in 1.6.4, thank you very much for the patch 3.

@ChristopherHX
Copy link
Member

Was your symptom before patchset 1 and 2 a black(or white) screen? Or did the process actually ended with exit code 0?

Saw one white and one black screen report in discord

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.

4 participants