Skip to content

Commit

Permalink
trace2: add child_start and child_exit events
Browse files Browse the repository at this point in the history
Write the TRACE2 child_start and child_exit events for each child
process invoked by GCM.
  • Loading branch information
Lessley Dennington authored and ldennington committed Mar 9, 2023
1 parent 0fb9284 commit 493154f
Show file tree
Hide file tree
Showing 9 changed files with 253 additions and 23 deletions.
2 changes: 1 addition & 1 deletion src/shared/Core/Authentication/AuthenticationBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ protected AuthenticationBase(ICommandContext context)
// authentication helper's messages.
Context.Trace.Flush();

var process = ChildProcess.Start(Context.Trace2, procStartInfo);
var process = ChildProcess.Start(Context.Trace2, procStartInfo, Trace2ProcessClass.UIHelper);
if (process is null)
{
throw new Exception($"Failed to start helper process: {path} {args}");
Expand Down
34 changes: 30 additions & 4 deletions src/shared/Core/ChildProcess.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public class ChildProcess : DisposableObject

private DateTimeOffset _startTime;
private DateTimeOffset _exitTime => Process.ExitTime;
private ProcessStartInfo _startInfo => Process.StartInfo;

private int _id => Process.Id;

Expand All @@ -19,26 +20,38 @@ public class ChildProcess : DisposableObject
public StreamWriter StandardInput => Process.StandardInput;
public StreamReader StandardOutput => Process.StandardOutput;
public StreamReader StandardError => Process.StandardError;
public int Id => Process.Id;
public int ExitCode => Process.ExitCode;

public static ChildProcess Start(ITrace2 trace2, ProcessStartInfo startInfo)
public static ChildProcess Start(ITrace2 trace2, ProcessStartInfo startInfo, Trace2ProcessClass processClass)
{
var childProc = new ChildProcess(trace2, startInfo);
childProc.Start();
childProc.Start(processClass);
return childProc;
}

public ChildProcess(ITrace2 trace2, ProcessStartInfo startInfo)
{
_trace2 = trace2;
Process = new Process() { StartInfo = startInfo };
Process.Exited += ProcessOnExited;
}

public void Start()
public void Start(Trace2ProcessClass processClass)
{
ThrowIfDisposed();
// Record the time just before the process starts, since:
// (1) There is no event related to Start as there is with Exit.
// (2) Using Process.StartTime causes a race condition that leads
// to an exception if the process finishes executing before the
// variable is passed to Trace2.
_startTime = DateTimeOffset.UtcNow;
Process.Start();
_trace2.WriteChildStart(
_startTime,
processClass,
_startInfo.UseShellExecute,
_startInfo.FileName,
_startInfo.Arguments);
}

public void WaitForExit() => Process.WaitForExit();
Expand All @@ -47,7 +60,20 @@ public void Start()

protected override void ReleaseManagedResources()
{
Process.Exited -= ProcessOnExited;
Process.Dispose();
base.ReleaseUnmanagedResources();
}

private void ProcessOnExited(object sender, EventArgs e)
{
if (sender is Process)
{
double elapsedTime = (_exitTime - _startTime).TotalSeconds;
_trace2.WriteChildExit(
elapsedTime,
_id,
Process.ExitCode);
}
}
}
2 changes: 1 addition & 1 deletion src/shared/Core/Diagnostics/GitDiagnostic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ protected override Task<bool> RunInternalAsync(StringBuilder log, IList<string>

log.Append("Listing all Git configuration...");
ChildProcess configProc = CommandContext.Git.CreateProcess("config --list --show-origin");
configProc.Start();
configProc.Start(Trace2ProcessClass.Git);
// To avoid deadlocks, always read the output stream first and then wait
// TODO: don't read in all the data at once; stream it
string gitConfig = configProc.StandardOutput.ReadToEnd().TrimEnd();
Expand Down
6 changes: 3 additions & 3 deletions src/shared/Core/Git.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public GitVersion Version
{
using (var git = CreateProcess("version"))
{
git.Start();
git.Start(Trace2ProcessClass.Git);

string data = git.StandardOutput.ReadToEnd();
git.WaitForExit();
Expand Down Expand Up @@ -120,7 +120,7 @@ public string GetCurrentRepository()
{
using (var git = CreateProcess("rev-parse --absolute-git-dir"))
{
git.Start();
git.Start(Trace2ProcessClass.Git);
string data = git.StandardOutput.ReadToEnd();
git.WaitForExit();

Expand All @@ -141,7 +141,7 @@ public IEnumerable<GitRemote> GetRemotes()
{
using (var git = CreateProcess("remote -v show"))
{
git.Start();
git.Start(Trace2ProcessClass.Git);
// To avoid deadlocks, always read the output stream first and then wait
// TODO: don't read in all the data at once; stream it
string data = git.StandardOutput.ReadToEnd();
Expand Down
18 changes: 9 additions & 9 deletions src/shared/Core/GitConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ public void Enumerate(GitConfigurationLevel level, GitConfigurationEnumerationCa
string levelArg = GetLevelFilterArg(level);
using (ChildProcess git = _git.CreateProcess($"config --null {levelArg} --list"))
{
git.Start();
git.Start(Trace2ProcessClass.Git);
// To avoid deadlocks, always read the output stream first and then wait
// TODO: don't read in all the data at once; stream it
string data = git.StandardOutput.ReadToEnd();
Expand Down Expand Up @@ -198,7 +198,7 @@ public bool TryGet(GitConfigurationLevel level, GitConfigurationType type, strin
string typeArg = GetCanonicalizeTypeArg(type);
using (ChildProcess git = _git.CreateProcess($"config --null {levelArg} {typeArg} {QuoteCmdArg(name)}"))
{
git.Start();
git.Start(Trace2ProcessClass.Git);
// To avoid deadlocks, always read the output stream first and then wait
// TODO: don't read in all the data at once; stream it
string data = git.StandardOutput.ReadToEnd();
Expand Down Expand Up @@ -236,7 +236,7 @@ public void Set(GitConfigurationLevel level, string name, string value)
string levelArg = GetLevelFilterArg(level);
using (ChildProcess git = _git.CreateProcess($"config {levelArg} {QuoteCmdArg(name)} {QuoteCmdArg(value)}"))
{
git.Start();
git.Start(Trace2ProcessClass.Git);
git.WaitForExit();

switch (git.ExitCode)
Expand All @@ -257,7 +257,7 @@ public void Add(GitConfigurationLevel level, string name, string value)
string levelArg = GetLevelFilterArg(level);
using (ChildProcess git = _git.CreateProcess($"config {levelArg} --add {QuoteCmdArg(name)} {QuoteCmdArg(value)}"))
{
git.Start();
git.Start(Trace2ProcessClass.Git);
git.WaitForExit();

switch (git.ExitCode)
Expand All @@ -278,7 +278,7 @@ public void Unset(GitConfigurationLevel level, string name)
string levelArg = GetLevelFilterArg(level);
using (ChildProcess git = _git.CreateProcess($"config {levelArg} --unset {QuoteCmdArg(name)}"))
{
git.Start();
git.Start(Trace2ProcessClass.Git);
git.WaitForExit();

switch (git.ExitCode)
Expand All @@ -302,7 +302,7 @@ public IEnumerable<string> GetAll(GitConfigurationLevel level, GitConfigurationT

using (ChildProcess git = _git.CreateProcess(gitArgs))
{
git.Start();
git.Start(Trace2ProcessClass.Git);
// To avoid deadlocks, always read the output stream first and then wait
// TODO: don't read in all the data at once; stream it
string data = git.StandardOutput.ReadToEnd();
Expand Down Expand Up @@ -344,7 +344,7 @@ public IEnumerable<string> GetRegex(GitConfigurationLevel level, GitConfiguratio

using (ChildProcess git = _git.CreateProcess(gitArgs))
{
git.Start();
git.Start(Trace2ProcessClass.Git);
// To avoid deadlocks, always read the output stream first and then wait
// TODO: don't read in all the data at once; stream it
string data = git.StandardOutput.ReadToEnd();
Expand Down Expand Up @@ -386,7 +386,7 @@ public void ReplaceAll(GitConfigurationLevel level, string name, string valueReg

using (ChildProcess git = _git.CreateProcess(gitArgs))
{
git.Start();
git.Start(Trace2ProcessClass.Git);
git.WaitForExit();

switch (git.ExitCode)
Expand All @@ -413,7 +413,7 @@ public void UnsetAll(GitConfigurationLevel level, string name, string valueRegex

using (ChildProcess git = _git.CreateProcess(gitArgs))
{
git.Start();
git.Start(Trace2ProcessClass.Git);
git.WaitForExit();

switch (git.ExitCode)
Expand Down
4 changes: 2 additions & 2 deletions src/shared/Core/PlatformUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ private static string GetOSVersion(ITrace2 trace2)

using (var swvers = new ChildProcess(trace2, psi))
{
swvers.Start();
swvers.Start(Trace2ProcessClass.Other);
swvers.WaitForExit();

if (swvers.ExitCode == 0)
Expand All @@ -359,7 +359,7 @@ private static string GetOSVersion(ITrace2 trace2)

using (var uname = new ChildProcess(trace2, psi))
{
uname.Start();
uname.Start(Trace2ProcessClass.Other);
uname.Process.WaitForExit();

if (uname.ExitCode == 0)
Expand Down
Loading

0 comments on commit 493154f

Please sign in to comment.