Skip to content

Commit f3cf894

Browse files
committed
Merge branch 'bug/166'
2 parents 4b66dd1 + f1b18a4 commit f3cf894

15 files changed

Lines changed: 542 additions & 12 deletions
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// UnityWebBrowser (UWB)
2+
// Copyright (c) 2021-2024 Voltstro-Studios
3+
//
4+
// This project is under the MIT license. See the LICENSE.md file for more details.
5+
6+
using System;
7+
using System.Diagnostics;
8+
using VoltstroStudios.UnityWebBrowser.Core.Engines.Process;
9+
using VoltstroStudios.UnityWebBrowser.Helper;
10+
using VoltstroStudios.UnityWebBrowser.Logging;
11+
12+
namespace VoltstroStudios.UnityWebBrowser.Core.Engines
13+
{
14+
/// <summary>
15+
/// Handler for the engine process
16+
/// </summary>
17+
internal sealed class EngineProcess : IDisposable
18+
{
19+
private readonly IProcess processHandle;
20+
private readonly Engine engine;
21+
private readonly IWebBrowserLogger logger;
22+
23+
/// <summary>
24+
/// Creates a new <see cref="EngineProcess"/> instance
25+
/// </summary>
26+
/// <param name="engine"></param>
27+
/// <param name="logger"></param>
28+
public EngineProcess(Engine engine, IWebBrowserLogger logger)
29+
{
30+
#if UNITY_STANDALONE_WIN
31+
processHandle = new WindowProcess();
32+
#elif UNITY_STANDALONE_LINUX
33+
processHandle = new LinuxProcess(logger);
34+
#endif
35+
36+
this.engine = engine;
37+
this.logger = logger;
38+
}
39+
40+
/// <summary>
41+
/// Has the process exited?
42+
/// </summary>
43+
public bool HasExited => processHandle.HasExited;
44+
45+
/// <summary>
46+
/// What was the exit code of the process
47+
/// </summary>
48+
public int ExitCode => processHandle.ExitCode;
49+
50+
/// <summary>
51+
/// Starts the engine process
52+
/// </summary>
53+
/// <param name="arguments"></param>
54+
/// <param name="onLogEvent"></param>
55+
/// <param name="onErrorLogEvent"></param>
56+
public void StartProcess(string arguments, DataReceivedEventHandler onLogEvent, DataReceivedEventHandler onErrorLogEvent)
57+
{
58+
string engineFullProcessPath = WebBrowserUtils.GetBrowserEngineProcessPath(engine);
59+
string engineDirectory = WebBrowserUtils.GetBrowserEnginePath(engine);
60+
61+
logger.Debug($"Process Path: '{engineFullProcessPath}'\nWorking: '{engineDirectory}'");
62+
logger.Debug($"Arguments: '{arguments}'");
63+
64+
processHandle.StartProcess(engineFullProcessPath, engineDirectory, arguments, onLogEvent, onErrorLogEvent);
65+
}
66+
67+
/// <summary>
68+
/// Kills the engine process
69+
/// </summary>
70+
public void KillProcess()
71+
{
72+
processHandle.KillProcess();
73+
}
74+
75+
public void Dispose()
76+
{
77+
processHandle.Dispose();
78+
}
79+
}
80+
}

src/Packages/UnityWebBrowser/Runtime/Core/Engines/EngineProcess.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Packages/UnityWebBrowser/Runtime/Core/Engines/Process.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// UnityWebBrowser (UWB)
2+
// Copyright (c) 2021-2024 Voltstro-Studios
3+
//
4+
// This project is under the MIT license. See the LICENSE.md file for more details.
5+
6+
using System;
7+
using System.Diagnostics;
8+
9+
namespace VoltstroStudios.UnityWebBrowser.Core.Engines.Process
10+
{
11+
internal interface IProcess : IDisposable
12+
{
13+
public void StartProcess(string executable, string workingDir, string arguments, DataReceivedEventHandler onLogEvent, DataReceivedEventHandler onErrorLogEvent);
14+
15+
public void KillProcess();
16+
17+
public bool HasExited { get; }
18+
19+
public int ExitCode { get; }
20+
}
21+
}

src/Packages/UnityWebBrowser/Runtime/Core/Engines/Process/IProcess.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// UnityWebBrowser (UWB)
2+
// Copyright (c) 2021-2024 Voltstro-Studios
3+
//
4+
// This project is under the MIT license. See the LICENSE.md file for more details.
5+
6+
#if UNITY_STANDALONE_LINUX
7+
8+
using System;
9+
using System.Collections.Generic;
10+
using System.Diagnostics;
11+
using System.IO;
12+
using VoltstroStudios.UnityWebBrowser.Logging;
13+
using VoltstroStudios.UnityWebBrowser.UnixSupport;
14+
15+
namespace VoltstroStudios.UnityWebBrowser.Core.Engines.Process
16+
{
17+
internal sealed class LinuxProcess : IProcess
18+
{
19+
private readonly System.Diagnostics.Process process;
20+
private readonly IWebBrowserLogger logger;
21+
22+
public LinuxProcess(IWebBrowserLogger logger)
23+
{
24+
process = new System.Diagnostics.Process();
25+
this.logger = logger;
26+
}
27+
28+
public bool HasExited { get; }
29+
public int ExitCode { get; }
30+
31+
public void StartProcess(string executable, string workingDir, string arguments, DataReceivedEventHandler onLogEvent,
32+
DataReceivedEventHandler onErrorLogEvent)
33+
{
34+
if (PermissionsManager.CheckAndSetIfNeededFileExecutablePermission(executable))
35+
logger.Warn(
36+
"UWB engine process did not have +rwx permissions! Engine process permission's were updated for the user.");
37+
38+
ProcessStartInfo startInfo = new(executable, arguments)
39+
{
40+
CreateNoWindow = true,
41+
UseShellExecute = false,
42+
RedirectStandardOutput = true,
43+
RedirectStandardError = true,
44+
WorkingDirectory = workingDir
45+
};
46+
47+
process.StartInfo = startInfo;
48+
process.OutputDataReceived += onLogEvent;
49+
process.ErrorDataReceived += onErrorLogEvent;
50+
process.Start();
51+
process.BeginOutputReadLine();
52+
process.BeginErrorReadLine();
53+
}
54+
55+
public void KillProcess()
56+
{
57+
TimeSpan timeout = TimeSpan.FromSeconds(30);
58+
HashSet<int> children = new();
59+
GetAllChildIdsUnix(process.Id, children, timeout);
60+
foreach (int childId in children) KillProcessUnix(childId, timeout);
61+
KillProcessUnix(process.Id, timeout);
62+
}
63+
64+
public void Dispose()
65+
{
66+
process.Dispose();
67+
}
68+
69+
private static void GetAllChildIdsUnix(int parentId, ISet<int> children, TimeSpan timeout)
70+
{
71+
int exitCode = RunProcessAndWaitForExit(
72+
"pgrep",
73+
$"-P {parentId}",
74+
timeout,
75+
out string stdout);
76+
77+
if (exitCode != 0 || string.IsNullOrEmpty(stdout)) return;
78+
using StringReader reader = new(stdout);
79+
while (true)
80+
{
81+
string text = reader.ReadLine();
82+
if (text == null) return;
83+
84+
if (!int.TryParse(text, out int id)) continue;
85+
86+
children.Add(id);
87+
// Recursively get the children
88+
GetAllChildIdsUnix(id, children, timeout);
89+
}
90+
}
91+
92+
private static void KillProcessUnix(int processId, TimeSpan timeout)
93+
{
94+
RunProcessAndWaitForExit(
95+
"kill",
96+
$"-TERM {processId}",
97+
timeout,
98+
out string _);
99+
}
100+
101+
private static int RunProcessAndWaitForExit(string fileName, string arguments, TimeSpan timeout,
102+
out string stdout)
103+
{
104+
ProcessStartInfo startInfo = new()
105+
{
106+
FileName = fileName,
107+
Arguments = arguments,
108+
RedirectStandardOutput = true,
109+
UseShellExecute = false,
110+
CreateNoWindow = true
111+
};
112+
113+
System.Diagnostics.Process process = System.Diagnostics.Process.Start(startInfo);
114+
115+
stdout = null;
116+
if (process.WaitForExit((int)timeout.TotalMilliseconds))
117+
stdout = process.StandardOutput.ReadToEnd();
118+
else
119+
process.Kill();
120+
121+
return process.ExitCode;
122+
}
123+
}
124+
}
125+
126+
#endif

src/Packages/UnityWebBrowser/Runtime/Core/Engines/Process/LinuxProcess.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)