From 35d91a0e58cb0b2916b7a4f138c63fcc12b71112 Mon Sep 17 00:00:00 2001
From: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
Date: Tue, 30 May 2023 01:48:37 +0200
Subject: Linux: Automatically increase vm.max_map_count if it's too low
 (#4702)

* memory: Check results of pinvoke calls

* Increase vm.max_map_count when running Ryujinx

* Add SupportedOSPlatform attribute for WindowsApiException

* Revert increasing vm.max_map_count via script

* Add LinuxHelper to detect and increase vm.max_map_count

With GUI dialogs, this should be a bit more user-friendly.

* Supply arguments as a list to RunPkExec

* Add error logging in case RunPkExec() fails

* Prevent Gtk from crashing
---
 src/Ryujinx.Ui.Common/Helper/LinuxHelper.cs | 62 +++++++++++++++++++++++++++++
 1 file changed, 62 insertions(+)
 create mode 100644 src/Ryujinx.Ui.Common/Helper/LinuxHelper.cs

(limited to 'src/Ryujinx.Ui.Common/Helper/LinuxHelper.cs')

diff --git a/src/Ryujinx.Ui.Common/Helper/LinuxHelper.cs b/src/Ryujinx.Ui.Common/Helper/LinuxHelper.cs
new file mode 100644
index 00000000..cfbf4b57
--- /dev/null
+++ b/src/Ryujinx.Ui.Common/Helper/LinuxHelper.cs
@@ -0,0 +1,62 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.Versioning;
+
+namespace Ryujinx.Ui.Common.Helper
+{
+    [SupportedOSPlatform("linux")]
+    public static class LinuxHelper
+    {
+        // NOTE: This value was determined by manual tests and might need to be increased again.
+        public const int RecommendedVmMaxMapCount = 524288;
+        public const string VmMaxMapCountPath = "/proc/sys/vm/max_map_count";
+        public const string SysCtlConfigPath = "/etc/sysctl.d/99-Ryujinx.conf";
+        public static int VmMaxMapCount => int.Parse(File.ReadAllText(VmMaxMapCountPath));
+        public static string PkExecPath { get; } = GetBinaryPath("pkexec");
+
+        private static string GetBinaryPath(string binary)
+        {
+            string pathVar = Environment.GetEnvironmentVariable("PATH");
+
+            if (pathVar is null || string.IsNullOrEmpty(binary))
+            {
+                return null;
+            }
+
+            foreach (var searchPath in pathVar.Split(":", StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries))
+            {
+                string binaryPath = Path.Combine(searchPath, binary);
+
+                if (File.Exists(binaryPath))
+                {
+                    return binaryPath;
+                }
+            }
+
+            return null;
+        }
+
+        public static int RunPkExec(string command)
+        {
+            if (PkExecPath == null)
+            {
+                return 1;
+            }
+
+            using Process process = new()
+            {
+                StartInfo =
+                {
+                    FileName = PkExecPath,
+                    ArgumentList = { "sh", "-c", command }
+                }
+            };
+
+            process.Start();
+            process.WaitForExit();
+
+            return process.ExitCode;
+        }
+    }
+}
\ No newline at end of file
-- 
cgit v1.2.3-70-g09d2