summaryrefslogtreecommitdiff
path: root/Source/Android/jni/MainAndroid.cpp
diff options
context:
space:
mode:
authorJosJuice <josjuice@gmail.com>2023-01-01 20:18:03 +0100
committerJosJuice <josjuice@gmail.com>2023-02-28 20:29:46 +0100
commit86c1f6e1e7e2abcc3f42e1182134e632b218b6d3 (patch)
tree21a12f638e632148a9ef82f6f6b696f8861ca41c /Source/Android/jni/MainAndroid.cpp
parent0cdae98181d8bef6f6e9c8a2783318c400101aa0 (diff)
Jit: Don't use a second stack
This second stack leads to JNI problems on Android, because ART fetches the address and size of the original stack using pthread functions (see GetThreadStack in art/runtime/thread.cc), and (presumably) treats stack addresses outside of the original stack as invalid. (What I don't understand is why some JNI operations on the CPU thread work fine despite this but others don't.) Instead of creating a second stack, let's borrow the approach ART uses: Use pthread functions to find out the stack's address and size, then install guard pages at an appropriate location. This lets us get rid of a workaround we had in the MsgAlert function. Because we're no longer choosing the stack size ourselves, I've made some tweaks to where the put the guard pages. Previously we had a stack of 2 MiB and a safe zone of 512 KiB. We now accept stacks as small as 512 KiB (used on macOS) and use a safe zone of 256 KiB. I feel like this should be fine, but haven't done much testing beyond "it seems to work". By the way, on Windows it was already the case that we didn't create a second stack... But there was a bug in the implementation! The code for protecting the stack has to run on the CPU thread, since it's the CPU thread's stack we want to protect, but it was actually running on EmuThread. This commit fixes that, since now this bug matters on other operating systems too.
Diffstat (limited to 'Source/Android/jni/MainAndroid.cpp')
-rw-r--r--Source/Android/jni/MainAndroid.cpp26
1 files changed, 9 insertions, 17 deletions
diff --git a/Source/Android/jni/MainAndroid.cpp b/Source/Android/jni/MainAndroid.cpp
index 7902a9973f..01728ce014 100644
--- a/Source/Android/jni/MainAndroid.cpp
+++ b/Source/Android/jni/MainAndroid.cpp
@@ -195,26 +195,18 @@ std::unique_ptr<GBAHostInterface> Host_CreateGBAHost(std::weak_ptr<HW::GBA::Core
static bool MsgAlert(const char* caption, const char* text, bool yes_no, Common::MsgType style)
{
- // If a panic alert happens very early in the execution of a game, we can crash here with
- // the error "JNI NewString called with pending exception java.lang.StackOverflowError".
- // As a workaround, let's put the call on a new thread with a brand new stack.
-
- jboolean result;
-
- std::thread([&] {
- JNIEnv* env = IDCache::GetEnvForThread();
+ JNIEnv* env = IDCache::GetEnvForThread();
- jstring j_caption = ToJString(env, caption);
- jstring j_text = ToJString(env, text);
+ jstring j_caption = ToJString(env, caption);
+ jstring j_text = ToJString(env, text);
- // Execute the Java method.
- result = env->CallStaticBooleanMethod(
- IDCache::GetNativeLibraryClass(), IDCache::GetDisplayAlertMsg(), j_caption, j_text, yes_no,
- style == Common::MsgType::Warning, s_need_nonblocking_alert_msg);
+ // Execute the Java method.
+ jboolean result = env->CallStaticBooleanMethod(
+ IDCache::GetNativeLibraryClass(), IDCache::GetDisplayAlertMsg(), j_caption, j_text, yes_no,
+ style == Common::MsgType::Warning, s_need_nonblocking_alert_msg);
- env->DeleteLocalRef(j_caption);
- env->DeleteLocalRef(j_text);
- }).join();
+ env->DeleteLocalRef(j_caption);
+ env->DeleteLocalRef(j_text);
return result != JNI_FALSE;
}