From 35949bce22b5de0a8bebb4fbd89615a09b0983f7 Mon Sep 17 00:00:00 2001 From: Hooder Date: Wed, 23 Feb 2022 02:41:00 +0100 Subject: [PATCH] gpu: Fix loading gluegen natives on some Windows configurations This commit works around a bug with loading natives when the user's home folder contains special characters such as `&`, `^` or `!`. When Gluegen loads native libraries on Windows, it uses a temporary directory located in `%appdata%` under the user's home directory, and Gluegen checks whether files can be executed from this temporary directory. To perform this check, it writes an executable to the directory, executes it, and ensures that the return code is zero. The executable file it writes is by default a `.bat` file, but it can be told to write an `.exe` file instead by supplying this VM argument: `-Djogamp.gluegen.UseNativeExeFile=true`. The default behaviour of writing and executing a `.bat` file is broken when the path to the temp folder contains a special character, due to a convoluted trail of calls that leads to undefined behaviour: - Gluegen attempts to execute the `.bat` file by calling `Runtime.exec()`: `Runtime.exec(new String[] { "...absolute path...bat" }, null, null)` - OpenJDK 11.0.8 passes the command to `ProcessBuilder`, which calls `ProcessImpl.start(...)`, which creates a new `ProcessImpl` instance. - In the `ProcessImpl` constructor, there are two different character escape modes: - **Legacy mode**, which allows ambiguous commands. - **Non-legacy mode**, which does more rigorous escaping. - Legacy is the default mode as long as `System.getSecurityManager()` returns `null`, which is the case for RuneLite currently. This mode can be changed by supplying the following VM argument: `-Djdk.lang.Process.allowAmbiguousCommands=false`. - Incidentally this also fixes the issue of loading natives with special characters in the path, however it applies to *all* `Runtime.exec()` calls. - In legacy mode, the command is wrapped in quotes if it contains either a space or tab character. The command is then passed along to the native function `Java_java_lang_ProcessImpl_create`, which eventually passes it along untouched to Microsoft's `CreateProcessW` function as the `lpCommandLine` argument. - In the documentation for this function, it is mentioned that an interpreter (i.e. `cmd.exe`) is required in order to run a `.bat` file. It is not specified what will happen if you instead pass the path to a `.bat` file directly to the function, which is what Gluegen ends up doing. However, `CreateProcessW` *does* support supplying the path to an `.exe`, which Gluegen will do when `jogamp.gluegen.UseNativeExeFile` is set to `true`. It is unclear why supplying a `.bat` file normally works, yet breaks when special characters are in the path. It seems like it should not work in the first place. This might help with #6509 and #14180. Some other special characters, like Cyrillic letters, are more fundamentally broken in RuneLite. This patch only slightly helps with that. --- .../main/java/net/runelite/client/plugins/gpu/GpuPlugin.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java index 232dd9d351..96c992f2da 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java @@ -353,6 +353,8 @@ public class GpuPlugin extends Plugin implements DrawCallbacks System.setProperty("jogl.debug", "true"); } + System.setProperty("jogamp.gluegen.UseNativeExeFile", "true"); + GLProfile.initSingleton(); invokeOnMainThread(() ->