0
0
mirror of https://github.com/sp-tarkov/patcher.git synced 2025-02-12 17:10:46 -05:00

Merge pull request 'fix-debug-process-hang' (#14) from fix-debug-process-hang into main

Reviewed-on: waffle.lord/Patcher#14
This commit is contained in:
IsWaffle 2023-11-17 17:40:15 +00:00
commit 241023c5fd
8 changed files with 194 additions and 70 deletions

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AvaloniaProject">
<option name="projectPerEditor">
<map>
<entry key="PatchClient/Views/MainWindow.axaml" value="PatchClient/PatchClient.csproj" />
<entry key="PatchGenerator/Views/MainWindow.axaml" value="PatchGenerator/PatchGenerator.csproj" />
</map>
</option>
</component>
</project>

View File

@ -7,6 +7,7 @@ using ReactiveUI;
using System.Reactive; using System.Reactive;
using System; using System;
using System.Linq; using System.Linq;
using System.Reflection;
using PatcherUtils.Model; using PatcherUtils.Model;
namespace PatchClient namespace PatchClient
@ -46,6 +47,10 @@ namespace PatchClient
PatchLogger.LogInfo("Running with autoclose"); PatchLogger.LogInfo("Running with autoclose");
} }
var version = Assembly.GetExecutingAssembly().GetName().Version;
PatchLogger.LogInfo($"Patch Client v{version?.ToString() ?? "N/A"}");
desktop.MainWindow = new MainWindow desktop.MainWindow = new MainWindow
{ {
DataContext = new MainWindowViewModel(autoClose, debugOutput), DataContext = new MainWindowViewModel(autoClose, debugOutput),

View File

@ -4,8 +4,8 @@
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract> <IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<AssemblyVersion>2.10.0</AssemblyVersion> <AssemblyVersion>2.10.2</AssemblyVersion>
<FileVersion>2.10.0</FileVersion> <FileVersion>2.10.2</FileVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<AvaloniaResource Include="Assets\**" /> <AvaloniaResource Include="Assets\**" />

View File

@ -7,6 +7,7 @@ using PatchGenerator.Views;
using ReactiveUI; using ReactiveUI;
using System.Reactive; using System.Reactive;
using System; using System;
using System.Reflection;
using PatcherUtils.Model; using PatcherUtils.Model;
namespace PatchGenerator namespace PatchGenerator
@ -26,6 +27,10 @@ namespace PatchGenerator
public override void OnFrameworkInitializationCompleted() public override void OnFrameworkInitializationCompleted()
{ {
var version = Assembly.GetExecutingAssembly().GetName().Version;
PatchLogger.LogInfo($"Patch Generator v{version?.ToString() ?? "N/A"}");
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{ {
desktop.Startup += Desktop_Startup; desktop.Startup += Desktop_Startup;

View File

@ -4,8 +4,8 @@
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract> <IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<AssemblyVersion>2.10.0</AssemblyVersion> <AssemblyVersion>2.10.2</AssemblyVersion>
<FileVersion>2.10.0</FileVersion> <FileVersion>2.10.2</FileVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

Binary file not shown.

View File

@ -0,0 +1,161 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;
using PatcherUtils.Model;
namespace PatcherUtils.Helpers;
public class XdeltaProcessHelper
{
private readonly int _timeout = (int)TimeSpan.FromMinutes(5).TotalMilliseconds;
private string _args;
private string _sourcePath;
private string _deltaPath;
private string _decodedPath;
private bool _isDebug;
public XdeltaProcessHelper(string args, string sourcePath, string deltaPath, string decodedPath, bool isDebug)
{
_args = args;
_sourcePath = sourcePath;
_deltaPath = deltaPath;
_decodedPath = decodedPath;
_isDebug = isDebug;
}
public bool Run() => _isDebug ? RunDebug() : RunNormal();
private bool RunNormal()
{
try
{
using var proc = new Process();
proc.StartInfo = new ProcessStartInfo
{
FileName = LazyOperations.XDelta3Path,
Arguments = $"{_args} \"{_sourcePath}\" \"{_deltaPath}\" \"{_decodedPath}\"",
CreateNoWindow = true
};
proc.Start();
if (!proc.WaitForExit(_timeout))
{
PatchLogger.LogError("xdelta3 process timed out");
PatchLogger.LogDebug($"xdelta exit code: {proc.ExitCode}");
return false;
}
PatchLogger.LogDebug($"xdelta exit code: {proc.ExitCode}");
return true;
}
catch (Exception ex)
{
PatchLogger.LogException(ex);
return false;
}
}
private bool DebugPathsCheck()
{
try
{
var stream = File.Open(_sourcePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
stream.Close();
stream.Dispose();
PatchLogger.LogDebug($"File is openable: {_sourcePath}");
}
catch (Exception ex)
{
PatchLogger.LogException(ex);
return false;
}
try
{
var stream = File.Open(_deltaPath, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
stream.Close();
stream.Dispose();
PatchLogger.LogDebug($"File is openable: {_deltaPath}");
}
catch (Exception ex)
{
PatchLogger.LogException(ex);
return false;
}
return true;
}
private bool RunDebug()
{
if (!DebugPathsCheck())
{
return false;
}
using var proc = new Process();
proc.StartInfo = new ProcessStartInfo
{
FileName = LazyOperations.XDelta3Path,
Arguments = $"{_args} \"{_sourcePath}\" \"{_deltaPath}\" \"{_decodedPath}\"",
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
};
var outputBuilder = new StringBuilder();
var errorBuilder = new StringBuilder();
using AutoResetEvent outputWaitHandle = new AutoResetEvent(false);
using AutoResetEvent errorWaitHandle = new AutoResetEvent(false);
proc.OutputDataReceived += (s, e) =>
{
if (e.Data == null)
{
outputWaitHandle.Set();
}
else
{
outputBuilder.AppendLine(e.Data);
}
};
proc.ErrorDataReceived += (s, e) =>
{
if (e.Data == null)
{
errorWaitHandle.Set();
}
else
{
errorBuilder.AppendLine(e.Data);
}
};
proc.Start();
proc.BeginOutputReadLine();
proc.BeginErrorReadLine();
if (!proc.WaitForExit(_timeout) || !outputWaitHandle.WaitOne(_timeout) || !errorWaitHandle.WaitOne(_timeout))
{
PatchLogger.LogError("xdelta3 process timed out");
PatchLogger.LogDebug($"xdelta exit code: {proc.ExitCode}");
return false;
}
PatchLogger.LogDebug("__xdelta stdout__");
PatchLogger.LogDebug(outputBuilder.ToString());
PatchLogger.LogDebug("__xdelta stderr__");
PatchLogger.LogDebug(errorBuilder.ToString());
PatchLogger.LogDebug($"xdelta exit code: {proc.ExitCode}");
return true;
}
}

View File

@ -6,6 +6,7 @@ using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Security.Cryptography; using System.Security.Cryptography;
using PatcherUtils.Helpers;
namespace PatcherUtils namespace PatcherUtils
{ {
@ -104,71 +105,12 @@ namespace PatcherUtils
var xdeltaArgs = $"-d {(debugOutput ? "-v -v" : "")} -f -s"; var xdeltaArgs = $"-d {(debugOutput ? "-v -v" : "")} -f -s";
if (debugOutput) var xdeltaHelper =
new XdeltaProcessHelper(xdeltaArgs, SourceFilePath, DeltaFilePath, decodedPath, debugOutput);
if (!xdeltaHelper.Run())
{ {
try return (false, "something went wrong during the xdelta3 process");
{
var stream = File.Open(SourceFilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
stream.Close();
stream.Dispose();
PatchLogger.LogDebug($"File is openable: {SourceFilePath}");
}
catch (Exception ex)
{
PatchLogger.LogException(ex);
}
try
{
var stream = File.Open(SourceFilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
stream.Close();
stream.Dispose();
PatchLogger.LogDebug($"File is openable: {DeltaFilePath}");
}
catch (Exception ex)
{
PatchLogger.LogException(ex);
}
}
var proc = Process.Start(new ProcessStartInfo
{
FileName = LazyOperations.XDelta3Path,
Arguments = $"{xdeltaArgs} \"{SourceFilePath}\" \"{DeltaFilePath}\" \"{decodedPath}\"",
RedirectStandardError = true,
RedirectStandardOutput = true,
CreateNoWindow = true
});
if (proc == null)
{
PatchLogger.LogError($"xdelta3 process failed to start: {nameof(proc)} is null");
return (false, "xdelta3 process failed to start");
}
proc.WaitForExit();
if (debugOutput)
{
try
{
PatchLogger.LogDebug($"xdelta exit code :: {proc.ExitCode}");
PatchLogger.LogDebug("___Dumping xdelta stdout___");
while (!proc.StandardOutput.EndOfStream)
{
PatchLogger.LogDebug(proc.StandardOutput.ReadLine());
}
PatchLogger.LogDebug("___Dumping xdelta stderr___");
while (!proc.StandardError.EndOfStream)
{
PatchLogger.LogDebug(proc.StandardError.ReadLine());
}
}
catch (Exception ex)
{
PatchLogger.LogException(ex);
}
} }
if (File.Exists(decodedPath)) if (File.Exists(decodedPath))