FEX-Emu / FEX-Emu/FEX

Barotrauma: Random memory corruption in .NET 8 (CoreCLR)

Open
#5,766 1 comment 0 reactions 0 assignees View on GitHub
Game related ml-report
Dominant language
C++
Stars
8k
Forks
351
Avg merge
12h 31m
Merged PRs (30d)
102

Description

**What Game**
[Barotrauma](https://store.steampowered.com/app/602960/Barotrauma/)

**Describe the bug**
Barotrauma (native Linux build, .NET 8 / CoreCLR, Steam appid 602960) reliably crashes during startup content loading under FEX with `System.AccessViolationException` / `NullReferenceException`. **The crash site is different on nearly every run**, always landing in unsafe/pointer or vectorized managed code across completely unrelated libraries (image decode, audio decode, network bit-packing, UTF-8 transcoding).

FEX itself reports nothing. With `SilentLog=0` and `OutputLog` set to a file, the log is 0 bytes across every run. Unfortunately no unsupported instruction or JIT diagnostic.

Mono-based .NET games work fine on this same setup (e.g. Celeste runs great) while CoreCLR does not.

**System**

| | |
|---|---|
| FEX | `FEX-Emu (2607)`, `fex-emu-armv8.4 2607-1~r` (PPA) |
| CPU | Qualcomm **Oryon** (Snapdragon X Elite) |
| Kernel | 7.0.0-27-generic, **4K pages** |
| Host | Ubuntu 26.04 LTS (aarch64) |
| RootFS | Ubuntu 24.04.3 LTS (FEXRootFSFetcher) |
| Game | Barotrauma 1.13.4.0 (ReleaseLinux), .NET 8.0.0, CoreCLR 8.0.23.53103 |
| Thunks | none enabled (`"ThunksDB": {}`) |

FEX config was otherwise stock (only `RootFS`, plus `SilentLog`/`OutputLog` for diagnostics).

**How to repro**

```bash
cd ~/.local/share/Steam/steamapps/common/Barotrauma
SteamAppId=602960 DOTNET_EnableWriteXorExecute=0 ./Barotrauma
```

Crashes within ~10–40s during content loading, before reaching the main menu. Steam must be running for the SteamAPI init to succeed.

`DOTNET_EnableWriteXorExecute=0` is **required** to get this far at all — see Workaround below.

## Observed crash sites (same binary, same config, different runs)

| Crash site | Subsystem |
|---|---|
| `System.Text.Unicode.Utf8Utility.TranscodeToUtf8(Char*, Int32, Byte*, Int32, ...)` | UTF-8 transcoding (vectorized) |
| `Barotrauma.Sounds.OggSound+d__12.MoveNext()` | audio loading |
| `NVorbis.VorbisCodebook.DecodeScalar(DataPacket)` | Vorbis decode |
| `MonoGame.Utilities.Imaging.stbi__getn(stbi__context, Byte*, Int32)` | PNG decode (stb_image) |
| `Lidgren.Network.NetBitWriter.WriteByte(Byte, Int32, Byte[], Int32)` | network bit-packing |

Exceptions are `System.AccessViolationException: Attempted to read or write protected memory` or `System.NullReferenceException`.

Exit codes vary across runs: `134` (SIGABRT via .NET FailFast), `139` (bare SIGSEGV with no managed message), and occasional hangs after the fatal error is printed.

**Partial workaround**:

`DOTNET_EnableWriteXorExecute=0` is required, otherwise CoreCLR dies much earlier and more consistently:

```
Description: The process was terminated due to an internal error in the .NET Runtime
at IP 0x... with exit code 0x80131506
Unhandled exception code c0000005
```

## Things that did NOT help

Runtime flags (each with `DOTNET_EnableWriteXorExecute=0`):
- `DOTNET_EnableHWIntrinsic=0`: made it *worse* (bare SIGSEGV, no managed error)
- `DOTNET_EnableAVX512F=0` + `DOTNET_PreferredVectorBitWidth=256`: no change
- `DOTNET_TieredCompilation=0` + `DOTNET_TieredPGO=0` + `DOTNET_ReadyToRun=0`
- `DOTNET_gcConcurrent=0`, `DOTNET_gcServer=0`, `DOTNET_GCgen0size=40000000` (1 GiB gen0): no change

FEX config:
- `SMCChecks=2` (FULL) — eliminated the silent hard crashes and restored clean managed exceptions, but did not stop the corruption
- `VectorTSOEnabled=1` + `MemcpySetTSOEnabled=1` — made it *worse* (earlier crash, no crash report)
- `TSOEnabled=1` (default) throughout

Versions:
- **FEX-2603 --> FEX-2607: no change in behaviour.** Hoping the `cmpxchg8b/16b` flag fix in 2605 was relevant, but it made no observable difference.

## Telemetry

Every run produces an identical `Barotrauma.telem`:

```
EVEX instructions (AVX512): 1
Crash mask: 2048
16/32/64/128bit CAS Tear: 0
64byte Split Locks: 0
```

`EVEX: 1` appears even with AVX-512 disabled in the JIT, and exactly 1 every run.

## Notes

- Not Proton-related: this is the native Linux build, no Wine (The Windows build under Proton fails similarly)
- Probably not a corrupt install — for example, one of my crashes occurred while decoding `Content/UI/InventoryUIAtlas.png` but I'm able to decode it just fine with my OS' image viewer.
- No kernel-level fault is logged (no segfault/trap in dmesg), and no coredump is produced for the SIGSEGV cases.
- Possibly related: #5527 (CoreCLR under FEX), though that is a deterministic hook/trampoline failure rather than random corruption?

Happy to run diagnostics, apply patches, etc--whatever helps here!

Contributor guide

Open the contributing guide

Research direction

Start with the supplied SteamAppId and DOTNET_EnableWriteXorExecute=0 reproduction command in the Barotrauma directory, then compare the varying crash sites and the FEX logs. Check the effects of SMCChecks=2 and the listed CoreCLR and FEX settings, with related issue #5527 as context. Done means identifying the source of the corruption and validating a fix that lets the game complete startup content loading.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, csharp, linux
Domain
operating-systems
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
28/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.