new attempt at fixing crash on some devices

This commit is contained in:
izzy2lost
2026-02-16 00:48:27 -05:00
parent 21135acac8
commit fce5a8d19f
3 changed files with 59 additions and 58 deletions
+2 -2
View File
@@ -30,8 +30,8 @@ android {
minSdk = 26
targetSdk = 36
versionCode = 4
versionName = "1.0.3"
versionCode = 5
versionName = "1.0.4"
ndk {
abiFilters += listOf("arm64-v8a")
@@ -1,5 +1,6 @@
#include <android/log.h>
#include <dlfcn.h>
#include <fcntl.h>
#include <signal.h>
#include <stdint.h>
#include <string.h>
@@ -9,6 +10,9 @@
namespace {
constexpr const char* kCrashTag = "xemu-android";
constexpr size_t kPathMax = 512;
static char g_inline_aio_flag_path[kPathMax];
static int GetTid() {
return static_cast<int>(syscall(SYS_gettid));
@@ -53,9 +57,28 @@ static void LogBacktrace() {
}
}
static void MarkInlineAioRequired() {
if (g_inline_aio_flag_path[0] == '\0') {
return;
}
int fd = open(g_inline_aio_flag_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd < 0) {
return;
}
static const char kValue[] = "1\n";
ssize_t ignored = write(fd, kValue, sizeof(kValue) - 1);
(void)ignored;
close(fd);
}
static void CrashHandler(int sig, siginfo_t* info, void* ucontext) {
(void)info;
(void)ucontext;
if (sig == SIGILL) {
MarkInlineAioRequired();
}
__android_log_print(ANDROID_LOG_ERROR, kCrashTag,
"Caught signal %d in tid %d", sig, GetTid());
LogBacktrace();
@@ -69,10 +92,22 @@ static void InstallCrashHandlers() {
sa.sa_sigaction = CrashHandler;
sa.sa_flags = SA_SIGINFO | SA_RESETHAND;
sigaction(SIGABRT, &sa, nullptr);
sigaction(SIGILL, &sa, nullptr);
sigaction(SIGSEGV, &sa, nullptr);
}
} // namespace
extern "C" void xemu_android_set_inline_aio_crash_flag_path(const char* path) {
if (!path) {
g_inline_aio_flag_path[0] = '\0';
return;
}
size_t len = strnlen(path, sizeof(g_inline_aio_flag_path) - 1);
memcpy(g_inline_aio_flag_path, path, len);
g_inline_aio_flag_path[len] = '\0';
}
__attribute__((constructor)) static void InstallCrashHandlersOnLoad() {
InstallCrashHandlers();
}
+22 -56
View File
@@ -11,12 +11,10 @@
#include <jni.h>
#include <climits>
#include <cctype>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <algorithm>
#include <string>
#include <vector>
#include <sys/stat.h>
@@ -207,64 +205,24 @@ static std::string JStringToString(JNIEnv* env, jstring value) {
return out;
}
static std::string ToLowerAscii(std::string value) {
std::transform(value.begin(), value.end(), value.begin(), [](unsigned char c) {
return static_cast<char>(std::tolower(c));
});
return value;
static bool HasInlineAioCrashFlag(const std::string& flag_path) {
if (flag_path.empty()) {
return false;
}
struct stat st {};
return stat(flag_path.c_str(), &st) == 0;
}
static std::string GetBuildField(JNIEnv* env, const char* field_name) {
jclass buildClass = env->FindClass("android/os/Build");
if (!buildClass) {
HasException(env, "Build class lookup");
return {};
}
jfieldID field = env->GetStaticFieldID(buildClass, field_name, "Ljava/lang/String;");
if (!field) {
HasException(env, field_name);
env->DeleteLocalRef(buildClass);
return {};
}
jstring value =
static_cast<jstring>(env->GetStaticObjectField(buildClass, field));
if (HasException(env, field_name)) {
env->DeleteLocalRef(buildClass);
return {};
}
std::string out = JStringToString(env, value);
if (value) {
env->DeleteLocalRef(value);
}
env->DeleteLocalRef(buildClass);
return out;
}
static bool ShouldEnableInlineAioWorkaround() {
static bool ShouldEnableInlineAioWorkaround(const std::string& crash_flag_path) {
const char* forced = SDL_getenv("XEMU_ANDROID_INLINE_AIO");
if (forced) {
return forced[0] != '\0' && forced[0] != '0';
}
JNIEnv* env = GetEnv();
if (!env) {
return false;
}
const std::string device = ToLowerAscii(GetBuildField(env, "DEVICE"));
const std::string product = ToLowerAscii(GetBuildField(env, "PRODUCT"));
const std::string model = ToLowerAscii(GetBuildField(env, "MODEL"));
static const char* kAffectedDevices[] = {
"duchamp",
};
for (const char* marker : kAffectedDevices) {
if (device == marker ||
product.find(marker) != std::string::npos ||
model.find(marker) != std::string::npos) {
return true;
}
if (HasInlineAioCrashFlag(crash_flag_path)) {
LogInfoFmt("Inline AIO enabled from crash marker: %s",
crash_flag_path.c_str());
return true;
}
return false;
@@ -357,6 +315,7 @@ struct SetupFiles {
std::string dvd;
std::string eeprom;
std::string config_path;
std::string inline_aio_flag_path;
};
static bool WriteConfigToml(const std::string& config_path,
@@ -473,6 +432,7 @@ static SetupFiles SyncSetupFiles() {
std::string base = std::string(basePath) + "/x1box";
EnsureDirExists(base);
out.eeprom = base + "/eeprom.bin";
out.inline_aio_flag_path = base + "/inline_aio_required.flag";
const std::string mcpxPath = GetPrefString(env, activity, "mcpxPath");
const std::string flashPath = GetPrefString(env, activity, "flashPath");
@@ -556,6 +516,7 @@ extern "C" int (*qemu_main)(void);
extern "C" void xemu_android_display_preinit(void);
extern "C" void xemu_android_display_wait_ready(void);
extern "C" void xemu_android_display_loop(void);
extern "C" void xemu_android_set_inline_aio_crash_flag_path(const char* path);
struct QemuLaunchContext {
int argc;
@@ -601,14 +562,19 @@ extern "C" int SDL_main(int argc, char* argv[]) {
SDL_GameControllerEventState(SDL_ENABLE);
LoadGameControllerMappingsFromAssets();
SetupFiles setup = SyncSetupFiles();
xemu_android_set_inline_aio_crash_flag_path(setup.inline_aio_flag_path.empty()
? nullptr
: setup.inline_aio_flag_path.c_str());
if (!SDL_getenv("XEMU_ANDROID_INLINE_AIO")) {
const bool use_inline_aio = ShouldEnableInlineAioWorkaround();
const bool use_inline_aio =
ShouldEnableInlineAioWorkaround(setup.inline_aio_flag_path);
setenv("XEMU_ANDROID_INLINE_AIO", use_inline_aio ? "1" : "0", 1);
LogInfoFmt("XEMU_ANDROID_INLINE_AIO=%s", use_inline_aio ? "1" : "0");
}
SetupFiles setup = SyncSetupFiles();
if (!setup.config_path.empty()) {
LogInfo("SDL_main: loading config");
xemu_settings_set_path(setup.config_path.c_str());