Skip to content

Commit

Permalink
Workaround[lwjgl]: Implement mitigation for an early EMUI linker hang.
Browse files Browse the repository at this point in the history
  • Loading branch information
artdeell committed Jan 22, 2024
1 parent 2f98f4c commit 693f90b
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 0 deletions.
18 changes: 18 additions & 0 deletions app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/Tools.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;

@SuppressWarnings("IOStreamConstructor")
Expand Down Expand Up @@ -1093,6 +1094,23 @@ public static int mesureTextviewHeight(TextView t) {
return t.getMeasuredHeight();
}

/**
* Check if the device is one of the devices that may be affected by the hanging linker issue.
* The device is affected if the linker causes the process to lock up when dlopen() is called within
* dl_iterate_phdr().
* For now, the only affected firmware that I know of is Android 5.1, EMUI 3.1 on MTK-based Huawei
* devices.
* @return if the device is affected by the hanging linker issue.
*/
public static boolean deviceHasHangingLinker() {
// Android Oreo and onwards have GSIs and most phone firmwares at that point were not modified
// *that* intrusively. So assume that we are not affected.
if(SDK_INT >= Build.VERSION_CODES.O) return false;
// Since the affected function in LWJGL is rarely used (and when used, it's mainly for debug prints)
// we can make the search scope a bit more broad and check if we are running on a Huawei device.
return Build.MANUFACTURER.toLowerCase(Locale.ROOT).contains("huawei");
}

public static class RenderersList {
public final List<String> rendererIds;
public final String[] rendererDisplayNames;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ public static void setJavaEnvironment(Activity activity, String jreHome) throws
envMap.put("POJAV_ZINK_PREFER_SYSTEM_DRIVER", "1");
if(PREF_VSYNC_IN_ZINK)
envMap.put("POJAV_VSYNC_IN_ZINK", "1");
if(Tools.deviceHasHangingLinker())
envMap.put("POJAV_EMUI_ITERATOR_MITIGATE", "1");


// The OPEN GL version is changed according
Expand Down
38 changes: 38 additions & 0 deletions app_pojavlauncher/src/main/jni/input_bridge_v3.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ jint JNI_OnLoad(JavaVM* vm, __attribute__((unused)) void* reserved) {
pojav_environ->mouseDownBuffer = (*pojav_environ->runtimeJNIEnvPtr_JRE)->GetDirectBufferAddress(pojav_environ->runtimeJNIEnvPtr_JRE, mouseDownBufferJ);
hookExec();
installLinkerBugMitigation();
installEMUIIteratorMititgation();
}

if(pojav_environ->dalvikJavaVMPtr == vm) {
Expand Down Expand Up @@ -294,6 +295,43 @@ void installLinkerBugMitigation() {
}
}

/**
* This function is meant as a substitute for SharedLibraryUtil.getLibraryPath() that just returns 0
* (thus making the parent Java function return null). This is done to avoid using the LWJGL's default function,
* which will hang the crappy EMUI linker by dlopen()ing inside of dl_iterate_phdr().
* @return 0, to make the parent Java function return null immediately.
* For reference: https://github.com/PojavLauncherTeam/lwjgl3/blob/fix_huawei_hang/modules/lwjgl/core/src/main/java/org/lwjgl/system/SharedLibraryUtil.java
*/
jint getLibraryPath_fix(__attribute__((unused)) JNIEnv *env,
__attribute__((unused)) jclass class,
__attribute__((unused)) jlong pLibAddress,
__attribute__((unused)) jlong sOutAddress,
__attribute__((unused)) jint bufSize){
return 0;
}

/**
* Install the linker hang mitigation that is meant to prevent linker hangs on old EMUI firmware.
*/
void installEMUIIteratorMititgation() {
if(getenv("POJAV_EMUI_ITERATOR_MITIGATE") == NULL) return;
__android_log_print(ANDROID_LOG_INFO, "EMUIIteratorFix", "Installing...");
JNIEnv* env = pojav_environ->runtimeJNIEnvPtr_JRE;
jclass sharedLibraryUtil = (*env)->FindClass(env, "org/lwjgl/system/SharedLibraryUtil");
if(sharedLibraryUtil == NULL) {
__android_log_print(ANDROID_LOG_ERROR, "EMUIIteratorFix", "Failed to find the target class");
(*env)->ExceptionClear(env);
return;
}
JNINativeMethod getLibraryPathMethod[] = {
{"getLibraryPath", "(JJI)I", &getLibraryPath_fix}
};
if((*env)->RegisterNatives(env, sharedLibraryUtil, getLibraryPathMethod, 1) != 0) {
__android_log_print(ANDROID_LOG_ERROR, "EMUIIteratorFix", "Failed to register the mitigation method");
(*env)->ExceptionClear(env);
}
}

void critical_set_stackqueue(jboolean use_input_stack_queue) {
pojav_environ->isUseStackQueueCall = (int) use_input_stack_queue;
}
Expand Down
1 change: 1 addition & 0 deletions app_pojavlauncher/src/main/jni/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ jstring convertStringJVM(JNIEnv* srcEnv, JNIEnv* dstEnv, jstring srcStr);

void hookExec();
void installLinkerBugMitigation();
void installEMUIIteratorMititgation();
JNIEXPORT jstring JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeClipboard(JNIEnv* env, jclass clazz, jint action, jbyteArray copySrc);

0 comments on commit 693f90b

Please sign in to comment.