dotnet / dotnet/runtime

[Mono][Android] pthread_setschedparam EINVAL in mono_thread_internal_set_priority aborts the process

Open
#133,897 2 comments 0 reactions 0 assignees View on GitHub
area-VM-meta-mono needs-author-action
Dominant language
C#
Stars
18.3k
Forks
5.6k
PR merge metrics
PR metrics pending

Description

### Description

On an Honor phone running Android 16, an Android game intermittently aborts while opening its multiplayer lobby, before connecting to a game server. The captured native crash is caused by `mono_thread_internal_set_priority` treating `EINVAL` from `pthread_setschedparam` as fatal.

**Evidence boundary:** The binary-level diagnosis and on-device workaround validation below are from an application embedding **Mono 6.12.0**. The reporter also observes crashes with the newer development build, whose project targets `net10.0-android`, but we have not captured a matching stack trace or established the exact runtime pack used by that installed build. This is **not a claim of a confirmed reproduction on .NET 10**. We are reporting here because the corresponding fatal error handling is also present in the modern Mono source maintained in this repository.

### Reproduction Steps

Observed application-level reproduction:

1. Launch the game on the affected device.
2. Open the multiplayer lobby without connecting to a specific server.
3. Intermittently, the process aborts with the error below.

Rebooting the phone can temporarily prevent the crash; it can later recur. Disabling Honor's game management feature did not prevent reproduction. Another phone did not show the same behavior, but this was not a controlled comparison of OS and package versions.

There is no standalone minimal reproducer yet. The condition that causes Android to return `EINVAL` has not been isolated.

### Expected behavior

Please assess whether failure to adjust a thread's priority can be handled without terminating the entire application, with sufficient diagnostics to investigate the rejected scheduling request. We are not assuming that every scheduling error should be ignored.

### Actual behavior

The captured error is:

```text
mono_thread_internal_set_priority: pthread_setschedparam failed, error: "Invalid argument" (22)
Fatal signal 6 (SIGABRT)
```

Android records the exit as `APP CRASH(NATIVE)`. The diagnosed native path runs through `libmonosgen-2.0.so`, the Mono logging handler in `libmonodroid.so` (`mono_log_handler` / `abort_application`), and `libc.so`'s `abort`.

### Configuration

- Device model: Honor PPG-AN00
- OS: Android 16, build `10.0.0.175(C00E175R104P7)`
- Architecture: arm64
- Application: Survivalcraft multiplayer, `API_Net_2_4`, versionCode `23050`
- Runtime in the diagnosed package: Mono `6.12.0`, build identifier `2020-02/d9a6e8710b3`

Hashes of the package's runtime libraries and the files actually used on the device were checked and matched.

### Regression?

Unknown. We do not have a controlled last-good runtime or OS version.

### Other information

#### Source analysis

At current main commit `1db0d832aa46443f8a4dcda42159be2a4c352d6a`:

- [The scheduling call and error handling](https://github.com/dotnet/runtime/blob/1db0d832aa46443f8a4dcda42159be2a4c352d6a/src/mono/mono/metadata/threads.c#L750-L769) warn and return for `EPERM`; other nonzero results, including `EINVAL`, reach `g_error`.
- [The thread-start wrapper](https://github.com/dotnet/runtime/blob/1db0d832aa46443f8a4dcda42159be2a4c352d6a/src/mono/mono/metadata/threads.c#L1117-L1148) calls the priority-setting function during startup, including for threads with the [default Normal priority](https://github.com/dotnet/runtime/blob/1db0d832aa46443f8a4dcda42159be2a4c352d6a/src/mono/mono/metadata/threads.c#L608). An explicit application call to `Thread.Priority` is therefore not required to reach this code.

This source inspection identifies a potentially affected modern path; it is separate from the legacy on-device evidence.

### Known Workarounds

#### Experiment on the diagnosed legacy binary

A local arm64 binary patch changed only the `EINVAL` case at this `pthread_setschedparam` failure branch to log a warning and return. Other error handling was retained; the patch did not attempt to reset the scheduling policy.

In the patched on-device log, the same `EINVAL` appeared three times as warnings, with no `Fatal signal 6` or `APP CRASH(NATIVE)` matches in that captured log. The game continued running, and opening and re-entering the lobby worked after applying the same patch to the original package. This demonstrates that this fatal path caused the diagnosed legacy crash, and that continuing was possible in the observed cases. It does not establish long-term safety or constitute a proposed production-ready runtime patch.

### Additional observations

#### Unresolved scheduling behavior

Thread snapshots in normal periods showed ordinary scheduling. During recurrence, some main/render threads were observed using FIFO real-time scheduling. We have **not** established who changed that policy or how it led to `EINVAL`, and do not attribute it to the OS vendor without further evidence.

Would it be appropriate to make this failure non-fatal on Android, and what additional diagnostics would help determine the upstream cause? In particular, recording the target thread identity, policy, requested scheduling priority and return code at the failing call would help distinguish invalid parameters, policy changes and device-specific behavior.

Contributor guide

Open the contributing guide

Research direction

Start in src/mono/mono/metadata/threads.c at mono_thread_internal_set_priority and its thread-start caller, then trace the pthread_setschedparam error handling for EINVAL. There is no standalone reproducer; done means reaching a documented, tested decision about non-fatal handling and diagnostics without assuming the legacy Mono 6.12 evidence reproduces on .NET 10.

Written by the indexing model from the issue text.

Assessment

Tech stack
android, c
Domain
mobile, operating-systems
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.