dotnet / dotnet/runtime

iOS: app killed with 0xdead10cc — StackTraceSymbols holds a shared flock on the PDB inside the app bundle

Open Beginner friendly
#133,697 4 comments 0 reactions 0 assignees View on GitHub
area-System.Diagnostics os-ios untriaged
Dominant language
C#
Stars
18.3k
Forks
5.6k
PR merge metrics
PR metrics pending

Description

### Description

On iOS, a .NET app running on CoreCLR is terminated by the OS a few seconds after it is
backgrounded, with `EXC_CRASH (SIGKILL)`, `RUNNINGBOARD`, code `0xdead10cc`. RunningBoard names
the offending file: the app's own **PDB, inside the app bundle**.

```
RunningBoard terminated [app:1710] because it was suspended
while holding a shared file lock:
/var/containers/Bundle/Application//MyApp.app/MyApp.pdb
File locks MUST be held in one of the following directories:
/var/mobile/Containers/Data/Application/
/var/mobile/Containers/Data/Application//tmp
```

Debug builds only — a Release build ships no PDB and is unaffected. This is a regression from the
switch to CoreCLR as the iOS runtime in .NET 11 (Mono read symbols through a different path).

### Analysis

1. `StackTraceSymbols.TryOpenFile` opens the PDB on the first stack trace that needs line numbers:

https://github.com/dotnet/runtime/blob/main/src/libraries/System.Diagnostics.StackTrace/src/System/Diagnostics/StackTraceSymbols.cs#L233

```csharp
// Open the file with read and delete FileShare flags. This matches what dll loading does
return new FileStream(path!, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete);
```

2. On Unix, any `FileShare` other than `None` maps to `flock(LOCK_SH)`
(`SafeFileHandle.Unix.cs`, `CanLockTheFile` / `LockOperations.LOCK_SH`).

3. The resulting `MetadataReaderProvider` is cached in a
`ConditionalWeakTable`. The key is the assembly, which lives
for the whole process, so **the lock is never released**.

4. At suspension, RunningBoard sees a file lock outside the app's data container and kills the app.

Setting `System.IO.DisableFileLocking=true` makes the termination disappear (verified on device,
iPad A16 / iOS 26.6.2), which confirms the chain — but it is a process-wide switch and disables
`FileShare` semantics everywhere, so it is not an acceptable general answer.

The comment's rationale does not hold on Unix: `dlopen` takes no advisory lock, so the shared
`flock` is not "what dll loading does" there.

### Proposed fix

Open the PDB with `FileShare.ReadWrite | FileShare.Delete`, which takes no advisory lock on Unix.
Nothing is lost: the file is opened read-only for symbol reading, and `FileShare.Delete` already
allows it to be removed underneath the reader.

### Repro

.NET 11 RC1 MAUI app, `net11.0-ios`, Debug, on a device (not the simulator — it is not suspended
the same way). Launch from the home screen, background it for 40 s (the kill happens at
suspension, not on entering the background), return. The app has been killed and cold-starts.
Objective check: sample the process id throughout, or read the RunningBoard log from a
sysdiagnose. Note that the crash report is not reliable as a signal — iOS throttles writing them
when the same app dies repeatedly.

I am happy to send the one-line PR if you would like it.

Contributor guide

Open the contributing guide

Research direction

Start in src/libraries/System.Diagnostics.StackTrace/src/System/Diagnostics/StackTraceSymbols.cs at TryOpenFile, then inspect SafeFileHandle.Unix.cs for the FileShare-to-flock behavior. Reproduce on a Debug net11.0-ios device by backgrounding the app and verify that symbol reading still works without the app being terminated for holding a bundle-file lock.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp, ios
Domain
mobile-dev, operating-systems
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
82/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.