Fix Android startup crash: move TMPDIR off FUSE so Realm can mkfifo() - #233
Conversation
…s; remove build_test/ Agent-Logs-Url: https://github.com/winnerspiros/osu/sessions/7c477ddd-0d71-4e47-8c12-f431f48789c7 Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Fixes an Android startup crash caused by Realm attempting to mkfifo() under a temp directory located on FUSE-backed external storage by moving TMPDIR to internal app cache, while keeping Mono --jitmap perfmap support for native crash symbolication.
Changes:
- Redirect Android
TMPDIRfrom external storage to internal cache (/data/user/0/.../cache) to allow Realm FIFO creation. - Update inline documentation/comments in the Android project and native crash handler to reflect the new temp/perfmap location and rationale.
- Remove committed diagnostic/build artifacts under
build_test/.
Reviewed changes
Copilot reviewed 5 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| osu.Android/osu.Android.csproj | Updates the <AndroidEnvironment> comment to reflect TMPDIR moving to internal cache and the Realm FIFO constraint. |
| osu.Android/mono.env | Changes TMPDIR to internal cache and documents why external storage breaks Realm mkfifo() notifiers. |
| osu.Android/Native/crash_handler.cpp | Updates perfmap/TMPDIR documentation to match the new internal-cache TMPDIR configuration. |
| build_test/archive.zip | Removes diagnostic capture artifact. |
| build_test/CMakeFiles/cmake.check_cache | Removes generated CMake artifact. |
| build_test/CMakeCache.txt | Removes generated CMake cache. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Candidate directories, in priority order. The dir containing g_logPath | ||
| // is checked first so a build that sets `TMPDIR=<external-files-dir>` | ||
| // (the recommended config) finds its perfmap immediately. | ||
| // (external files dir) is checked first as a historical fallback, but | ||
| // current builds set TMPDIR to the app's internal cache dir (FUSE-backed | ||
| // external storage cannot host the FIFOs Realm needs — see mono.env), so | ||
| // the perfmap normally lives at $TMPDIR/perf-<pid>.map. |
There was a problem hiding this comment.
With TMPDIR now recommended to point to internal cache, ensurePerfmapLoaded() will usually fail the first lookup attempt in the external-files log directory before trying $TMPDIR. Since this runs in the crash handler, consider reordering the candidate directories to check getenv("TMPDIR") first (and only fall back to the log dir), to reduce crash-time syscalls and simplify the “priority order” comment.
APK crashes on every launch with
RealmException: Failed to create fifo at '/storage/emulated/0/Android/data/sh.ppy.osulazer/files/lazer/realm_*.cv': Permission denied (13), thrown fromRealmAccess..ctorbefore the file logger initialises (so noosu.logis ever written).Root cause
RealmAccess.getConfiguration()sets:On Android,
Path.GetTempPath()returns$TMPDIR.osu.Android/mono.envwas settingTMPDIRto the app's external-files dir to make Mono's--jitmapperfmap user-retrievable — but that path is FUSE-backed, and the Linux kernel rejectsmkfifo()on FUSE mounts withEACCES. Realm needs FIFOs for its cross-process notifier (.cv/.note), soRealm.GetInstance()throws on every startup. The diagnostic capture inbuild_test/archive.zip(three successiveclient_*_corrupt.realmfiles + emptylogs/) confirmed RealmAccess's corrupt-recovery branch was firing on every launch and the crash was pre-logger.Changes
osu.Android/mono.env: pointTMPDIRat internal app cache (/data/user/0/sh.ppy.osulazer/cache), which is ext4/f2fs-backed and supports FIFOs. Document the FUSE/mkfifoconstraint inline so this doesn't regress.osu.Android/Native/crash_handler.cpp: update the perfmap-location comments to reflect the new TMPDIR. No code change —ensurePerfmapLoaded()already readsgetenv("TMPDIR")at signal time, so JIT-frame symbolication keeps working; the symbolicated output still lands innative_crash.login the external files dir, which remains user-retrievable.osu.Android/osu.Android.csproj: refresh the<AndroidEnvironment>comment for the same reason.build_test/: delete the diagnostic capture (archive.zip, native_crash.log, CMake leftovers) per request.Note on the missing crash log
The user's report came via
XamarinUncaughtExceptionHandler— a managed exception, not a native signal — so the native crash handler had nothing to capture and produced nonative_crash.log. Future native crashes will still be captured normally once Realm initialises.