You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
==========================
MAJOR FEATURES + CHANGES
==========================
Change 2877442 on 2016/02/23 by Graeme.Thornton@GThornton_DevCore
Allow 'dumpnonframe' stat command to also take an optional group name which will filter the output
Change 2879289 on 2016/02/24 by Graeme.Thornton@GThornton_DevCore
Removed "-" in switch string for load time tracker. Makes -NoLoadTrackClear cmd line param actually work
Change 2879323 on 2016/02/24 by Graeme.Thornton@GThornton_DevCore
PC builds now log engine initialization time with the load time tracker
Change 2879418 on 2016/02/24 by Graeme.Thornton@GThornton_DevCore
Optimization for FSignedArchiveReader
- Compute incoming data hash in parallel on another thread while we serialize and decrypt the signature on the chunk cache worker thread
Change 2879419 on 2016/02/24 by Graeme.Thornton@GThornton_DevCore
Extra stats for PakFile group
- Time reading from pak handles
- Number of open pak handles
Change 2881199 on 2016/02/25 by Graeme.Thornton@GThornton_DevCore
Use 32 bit CRCs to hash chunk contents rather than SHA1. Much faster to compute than SHA1, and the decrypting 4 bytes rather than 20 is also a lot faster
Change 2885687 on 2016/02/29 by Robert.Manuszewski@Robert.Manuszewski_NCL_Stream1
Close disregard for GC pool when disabling it to leave it in a good state.
Change 2887358 on 2016/03/01 by Steve.Robb@Dev-Core
FlushCurrentThreadCache calls forwarded on from FMalloc wrappers.
Change 2887398 on 2016/03/01 by Steve.Robb@Dev-Core
Stats for MallocBinned2.
Change 2887682 on 2016/03/01 by Robert.Manuszewski@Robert.Manuszewski_NCL_Stream1
Added code to catch game hangs. If game thread is stalled for more than 5 seconds we will catch that, report its callstack and crash.
Change 2889573 on 2016/03/02 by Robert.Manuszewski@Robert.Manuszewski_NCL_Stream1
Renamed the new StackWalkAndDump to ThreadStackWalkAndDump to avoid name collisions and build errors.
Change 2889687 on 2016/03/02 by Robert.Manuszewski@Robert.Manuszewski_NCL_Stream1
Send thread heartbeats during potentially slow tasks.
Change 2889963 on 2016/03/02 by Robert.Manuszewski@Robert.Manuszewski_NCL_Stream1
Added the ability to query the name of a thread given its TLS id.
Change 2890439 on 2016/03/02 by Steve.Robb@Dev-Core
MallocBinned redirection header, to allow easy switching between MallocBinned and MallocBinned2.
Switch back to MallocBinned by default.
Change 2891799 on 2016/03/03 by Steve.Robb@Dev-Core
Shrunken GMallocBinned2MemSizeToIndex array.
Improvement of some shared templated alignment-related functions.
Change 2891812 on 2016/03/03 by Graeme.Thornton@GThornton_DevCore
Refactoring of pak signing to be more compatible with patching
- Store signatures in a block at the end of the pak file
- Optimize decryption of signatures by serializing them all when the pak is opened, and decrypting on the chunk cache worker thread between read requests.
Change 2891813 on 2016/03/03 by Robert.Manuszewski@Robert.Manuszewski_NCL_Stream2
Don't compile UnrealPak with ICU
Change 2892386 on 2016/03/03 by Steve.Robb@Dev-Core
GitHub #2070 - Fix incorrect FMallocDebug::Malloc alignment checking
Change 2894189 on 2016/03/04 by Steve.Robb@Dev-Core
Memswap fixes for sizes of 3, 5, 6 and 7, and early out on 0.
Change 2894427 on 2016/03/04 by Robert.Manuszewski@Robert.Manuszewski_NCL_Stream1
Don't display message boxes in unattended mode when D3D device is removed.
Change 2896912 on 2016/03/07 by Graeme.Thornton@GThornton_DevCore
Disable reading of anything outside the pak file when in shipping builds
Change 2897053 on 2016/03/07 by Robert.Manuszewski@Robert.Manuszewski_NCL_Stream1
A few improvements to thread heartbeat thread:
- Don't check for heartbeat in debug builds
- Don't spawn the thread heartbeat thread for programs
- Ignore stalls when exiting
Change 2898752 on 2016/03/08 by Robert.Manuszewski@Robert.Manuszewski_NCL_Stream1
Fixing race conditions when using malloc verify
Change 2899075 on 2016/03/08 by Robert.Manuszewski@Robert.Manuszewski_NCL_Stream1
UnrealPak will now accept hex values for p and q. Added the command line param to trust p and q.
Change 2899091 on 2016/03/08 by Steve.Robb@Dev-Core
Fix for TQueue::Peek const-correctness.
Change 2902775 on 2016/03/10 by Robert.Manuszewski@Robert.Manuszewski_NCL_Stream1
Adding code to test signature keys.
Change 2905040 on 2016/03/11 by Robert.Manuszewski@Robert.Manuszewski_NCL_Stream1
TBigInt Multiply is now 30x faster
Change 2905218 on 2016/03/11 by Steve.Robb@Dev-Core
New FCString::Strspn and FCString::Strcspn functions.
[CL 2921423 by Robert Manuszewski in Main branch]
233 lines
7.3 KiB
C#
233 lines
7.3 KiB
C#
// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
|
|
namespace Tools.DotNETCommon.LaunchProcess
|
|
{
|
|
/// <summary>
|
|
/// Enum to make the meaning of WaitForExit return code clear
|
|
/// </summary>
|
|
public enum EWaitResult
|
|
{
|
|
/// <summary>The task completed in a timely manner</summary>
|
|
Ok,
|
|
|
|
/// <summary>The task was abandoned, since it was taking longer than the specified time-out duration</summary>
|
|
TimedOut
|
|
}
|
|
|
|
/// <summary>
|
|
/// A class to handle spawning and monitoring of a child process
|
|
/// </summary>
|
|
public class LaunchProcess : IDisposable
|
|
{
|
|
/// <summary>A callback signature for handling logging.</summary>
|
|
public delegate void CaptureMessageDelegate( string Message );
|
|
/// <summary>The current callback for logging, or null for quiet operation.</summary>
|
|
CaptureMessageDelegate CaptureMessage = null;
|
|
|
|
/// <summary>The process that was launched.</summary>
|
|
private Process LaunchedProcess = null;
|
|
/// <summary>Set to true when the launched process finishes.</summary>
|
|
private bool bIsFinished = false;
|
|
|
|
/// <summary>
|
|
/// Implementing Dispose.
|
|
/// </summary>
|
|
public void Dispose()
|
|
{
|
|
Dispose( true );
|
|
GC.SuppressFinalize( this );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Disposes the resources.
|
|
/// </summary>
|
|
/// <param name="Disposing"></param>
|
|
protected virtual void Dispose( bool Disposing )
|
|
{
|
|
LaunchedProcess.Dispose();
|
|
}
|
|
|
|
/// <summary>
|
|
/// The process exit event.
|
|
/// </summary>
|
|
/// <param name="Sender">Unused.</param>
|
|
/// <param name="Args">Unused.</param>
|
|
private void ProcessExit( object Sender, EventArgs Args )
|
|
{
|
|
// Flush and close any pending messages
|
|
if( CaptureMessage != null )
|
|
{
|
|
LaunchedProcess.CancelOutputRead();
|
|
LaunchedProcess.CancelErrorRead();
|
|
|
|
// Protect against multiple calls
|
|
CaptureMessage = null;
|
|
}
|
|
|
|
LaunchedProcess.EnableRaisingEvents = false;
|
|
bIsFinished = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Safely invoke the logging callback.
|
|
/// </summary>
|
|
/// <param name="Message">The line of text to pass back to the calling process via the delegate.</param>
|
|
private void PrintLog( string Message )
|
|
{
|
|
if( CaptureMessage != null )
|
|
{
|
|
CaptureMessage( Message );
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The event called for StdOut an StdErr redirections.
|
|
/// </summary>
|
|
/// <param name="Sender">Unused.</param>
|
|
/// <param name="Args">The container for the line of text to pass through the system.</param>
|
|
private void CaptureMessageCallback( object Sender, DataReceivedEventArgs Args )
|
|
{
|
|
PrintLog( Args.Data );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check to see if the currently running child process has finished.
|
|
/// </summary>
|
|
/// <returns>true if the process was successfully spawned and correctly exited. It also returns true if the process failed to spawn.</returns>
|
|
public bool IsFinished()
|
|
{
|
|
if( LaunchedProcess != null )
|
|
{
|
|
if( bIsFinished )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
// Check for timed out
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Wait for the launched process to exit, and return its exit code.
|
|
/// </summary>
|
|
/// <param name="TimeoutMilliseconds">Number of milliseconds to wait for the process to exit. Default is forever.</param>
|
|
/// <returns>The exit code of the launched process.</returns>
|
|
/// <remarks>false is returned if the process failed to finish before the requested timeout.</remarks>
|
|
public EWaitResult WaitForExit( int TimeoutMilliseconds = Int32.MaxValue )
|
|
{
|
|
if( LaunchedProcess != null )
|
|
{
|
|
LaunchedProcess.WaitForExit(TimeoutMilliseconds);
|
|
if( !bIsFinished )
|
|
{
|
|
// Calling Kill() here seems to be a race condition on the process terminating after WaitForExit (TTP#315685). Catch anything it throws, and make sure the Kill() finishes.
|
|
try
|
|
{
|
|
LaunchedProcess.Kill();
|
|
LaunchedProcess.WaitForExit();
|
|
}
|
|
catch (Exception)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
|
|
return bIsFinished ? EWaitResult.Ok : EWaitResult.TimedOut;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Construct a class wrapper that spawns a new child process with StdOut and StdErr optionally redirected and captured.
|
|
/// </summary>
|
|
/// <param name="Executable">The executable to launch.</param>
|
|
/// <param name="WorkingDirectory">The working directory of the process. If this is null, the current directory is used.</param>
|
|
/// <param name="InCaptureMessage">The log callback function. This can be null for no logging.</param>
|
|
/// <param name="Parameters">A string array of parameters passed on the command line, and delimited with spaces.</param>
|
|
/// <remarks>Any errors are passed back through the capture delegate. The existence of the executable and the working directory are checked before spawning is attempted.
|
|
/// An exit code of -1 is returned if there was an exception when spawning the process.</remarks>
|
|
public LaunchProcess( string Executable, string WorkingDirectory, CaptureMessageDelegate InCaptureMessage, params string[] Parameters )
|
|
{
|
|
CaptureMessage = InCaptureMessage;
|
|
|
|
// Simple check to ensure the executable exists
|
|
FileInfo Info = new FileInfo( Executable );
|
|
if( !Info.Exists )
|
|
{
|
|
PrintLog( "ERROR: Executable does not exist: " + Executable );
|
|
bIsFinished = true;
|
|
return;
|
|
}
|
|
|
|
// Set the default working directory if necessary
|
|
if( WorkingDirectory == null )
|
|
{
|
|
WorkingDirectory = Environment.CurrentDirectory;
|
|
}
|
|
|
|
// Simple check to ensure the working directory exists
|
|
DirectoryInfo DirInfo = new DirectoryInfo( WorkingDirectory );
|
|
if( !DirInfo.Exists )
|
|
{
|
|
PrintLog( "ERROR: Working directory does not exist: " + WorkingDirectory );
|
|
bIsFinished = true;
|
|
return;
|
|
}
|
|
|
|
// Create a new process to launch
|
|
LaunchedProcess = new Process();
|
|
|
|
// Prepare a ProcessStart structure
|
|
LaunchedProcess.StartInfo.FileName = Info.FullName;
|
|
LaunchedProcess.StartInfo.Arguments = String.Join( " ", Parameters );
|
|
LaunchedProcess.StartInfo.WorkingDirectory = DirInfo.FullName;
|
|
LaunchedProcess.StartInfo.CreateNoWindow = true;
|
|
|
|
// Need this for the Exited event as well as the output capturing
|
|
LaunchedProcess.EnableRaisingEvents = true;
|
|
LaunchedProcess.Exited += new EventHandler(ProcessExit);
|
|
|
|
// Redirect the output.
|
|
if (CaptureMessage != null)
|
|
{
|
|
LaunchedProcess.StartInfo.UseShellExecute = false;
|
|
LaunchedProcess.StartInfo.RedirectStandardOutput = true;
|
|
LaunchedProcess.StartInfo.RedirectStandardError = true;
|
|
|
|
LaunchedProcess.OutputDataReceived += new DataReceivedEventHandler(CaptureMessageCallback);
|
|
LaunchedProcess.ErrorDataReceived += new DataReceivedEventHandler(CaptureMessageCallback);
|
|
}
|
|
|
|
// Spawn the process - try to start the process, handling thrown exceptions as a failure.
|
|
try
|
|
{
|
|
PrintLog( "Launching: " + LaunchedProcess.StartInfo.FileName + " " + LaunchedProcess.StartInfo.Arguments + " (CWD: " + LaunchedProcess.StartInfo.WorkingDirectory + ")" );
|
|
|
|
LaunchedProcess.Start();
|
|
|
|
// Start the output redirection if we have a logging callback
|
|
if( CaptureMessage != null )
|
|
{
|
|
LaunchedProcess.BeginOutputReadLine();
|
|
LaunchedProcess.BeginErrorReadLine();
|
|
}
|
|
}
|
|
catch( Exception Ex )
|
|
{
|
|
// Clean up should there be any exception
|
|
LaunchedProcess = null;
|
|
bIsFinished = true;
|
|
PrintLog( "ERROR: Failed to launch with exception: " + Ex.Message );
|
|
}
|
|
}
|
|
}
|
|
}
|