From fd4e48f96e8328bbace2d4df4f2a6f7ab9a699f1 Mon Sep 17 00:00:00 2001
From: lat9nq <lat9nq@gmail.com>
Date: Sun, 10 Jul 2022 17:01:37 -0400
Subject: [PATCH] startup_checks: Implement unix side code

Wow fork() is nice, isn't it?
---
 src/yuzu/main.cpp           | 12 +--------
 src/yuzu/startup_checks.cpp | 53 ++++++++++++++++++++++++++++++++-----
 2 files changed, 48 insertions(+), 17 deletions(-)

diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index a2b11fdbf4..69f9cdd9ca 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -3852,19 +3852,9 @@ void GMainWindow::SetDiscordEnabled([[maybe_unused]] bool state) {
 
 int main(int argc, char* argv[]) {
     bool has_broken_vulkan = false;
-#ifdef _WIN32
-    char variable_contents[32];
-    const DWORD startup_check_var =
-        GetEnvironmentVariable(STARTUP_CHECK_ENV_VAR, variable_contents, 32);
-    const std::string variable_contents_s{variable_contents};
-    if (startup_check_var > 0 && variable_contents_s == "ON") {
-        CheckVulkan();
+    if (StartupChecks(argv[0], &has_broken_vulkan)) {
         return 0;
     }
-    StartupChecks(argv[0], &has_broken_vulkan);
-#elif YUZU_UNIX
-#error "Unimplemented"
-#endif
 
     Common::DetachedTasks detached_tasks;
     MicroProfileOnThreadCreate("Frontend");
diff --git a/src/yuzu/startup_checks.cpp b/src/yuzu/startup_checks.cpp
index c860f0aa03..6bd895400a 100644
--- a/src/yuzu/startup_checks.cpp
+++ b/src/yuzu/startup_checks.cpp
@@ -8,6 +8,8 @@
 #include <processthreadsapi.h>
 #include <windows.h>
 #elif defined(YUZU_UNIX)
+#include <errno.h>
+#include <sys/wait.h>
 #include <unistd.h>
 #endif
 
@@ -36,9 +38,20 @@ void CheckVulkan() {
 
 bool StartupChecks(const char* arg0, bool* has_broken_vulkan) {
 #ifdef _WIN32
+    // Check environment variable to see if we are the child
+    char variable_contents[32];
+    const DWORD startup_check_var =
+        GetEnvironmentVariable(STARTUP_CHECK_ENV_VAR, variable_contents, 32);
+    const std::string variable_contents_s{variable_contents};
+    if (startup_check_var > 0 && variable_contents_s == "ON") {
+        CheckVulkan();
+        return true;
+    }
+
+    // Set the startup variable for child processes
     const bool env_var_set = SetEnvironmentVariableA(STARTUP_CHECK_ENV_VAR, "ON");
     if (!env_var_set) {
-        std::fprintf(stderr, "SetEnvironmentVariableA failed to set %s, %d\n",
+        std::fprintf(stderr, "SetEnvironmentVariableA failed to set %s with error %d\n",
                      STARTUP_CHECK_ENV_VAR, GetLastError());
         return false;
     }
@@ -53,15 +66,43 @@ bool StartupChecks(const char* arg0, bool* has_broken_vulkan) {
     // wait until the processs exits
     DWORD exit_code = STILL_ACTIVE;
     while (exit_code == STILL_ACTIVE) {
-        GetExitCodeProcess(process_info.hProcess, &exit_code);
+        const int err = GetExitCodeProcess(process_info.hProcess, &exit_code);
+        if (err == 0) {
+            std::fprintf(stderr, "GetExitCodeProcess failed with error %d\n", GetLastError());
+            break;
+        }
     }
 
     *has_broken_vulkan = (exit_code != 0);
 
-    CloseHandle(process_info.hProcess);
-    CloseHandle(process_info.hThread);
+    if (CloseHandle(process_info.hProcess) == 0) {
+        std::fprintf(stderr, "CloseHandle failed with error %d\n", GetLastError());
+    }
+    if (CloseHandle(process_info.hThread) == 0) {
+        std::fprintf(stderr, "CloseHandle failed with error %d\n", GetLastError());
+    }
+
+#elif defined(YUZU_UNIX)
+    const pid_t pid = fork();
+    if (pid == 0) {
+        CheckVulkan();
+        return true;
+    } else if (pid == -1) {
+        const int err = errno;
+        std::fprintf(stderr, "fork failed with error %d\n", err);
+        return false;
+    }
+
+    int status;
+    const int r_val = wait(&status);
+    if (r_val == -1) {
+        const int err = errno;
+        std::fprintf(stderr, "wait failed with error %d\n", err);
+        return false;
+    }
+    *has_broken_vulkan = (status != 0);
 #endif
-    return true;
+    return false;
 }
 
 #ifdef _WIN32
@@ -87,7 +128,7 @@ bool SpawnChild(const char* arg0, PROCESS_INFORMATION* pi) {
                                                 pi             // lpProcessInformation
     );
     if (!process_created) {
-        std::fprintf(stderr, "CreateProcessA failed, %d\n", GetLastError());
+        std::fprintf(stderr, "CreateProcessA failed with error %d\n", GetLastError());
         return false;
     }