Skip to content

Commit 12632f3

Browse files
committed
Save per-thread forking state, interrupt over the pipe rat6her than using the mi
1 parent 17d1f39 commit 12632f3

File tree

11 files changed

+415
-177
lines changed

11 files changed

+415
-177
lines changed

src/DebugEngineHost.Stub/DebugEngineHost.ref.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -317,9 +317,9 @@ public static void FindNatvisInSolution(NatvisLoader loader)
317317
public static class HostDebugger
318318
{
319319
/// <summary>
320-
/// Attach to a process using the provided options
320+
/// Ask the host to async spin up a new instance of the debug engine and go through the launch sequence using the specified options
321321
/// </summary>
322-
public static void Attach(string filePath, string options, Guid engineId)
322+
public static void StartDebugChildProcess(string filePath, string options, Guid engineId)
323323
{
324324
throw new NotImplementedException();
325325
}

src/DebugEngineHost/HostDebugger.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
using System;
1+
// Copyright (c) Microsoft. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using System;
25
using Microsoft.VisualStudio.Shell.Interop;
36
using Microsoft.VisualStudio.Shell;
47
using Microsoft.VisualStudio;
@@ -15,9 +18,9 @@ namespace Microsoft.DebugEngineHost
1518
public static class HostDebugger
1619
{
1720
/// <summary>
18-
/// Attach to a process using the provided options
21+
/// Ask the host to async spin up a new instance of the debug engine and go through the launch sequence using the specified options
1922
/// </summary>
20-
public static void Attach(string filePath, string options, Guid engineId)
23+
public static void StartDebugChildProcess(string filePath, string options, Guid engineId)
2124
{
2225
try
2326
{

src/MICore/Debugger.cs

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public class Debugger : ITransportCallback
3838
public event EventHandler BreakCreatedEvent; // a breakpoint was created
3939
public event EventHandler ThreadCreatedEvent;
4040
public event EventHandler ThreadExitedEvent;
41+
public event EventHandler ThreadGroupExitedEvent;
4142
public event EventHandler<ResultEventArgs> MessageEvent;
4243
public event EventHandler<ResultEventArgs> TelemetryEvent;
4344
private int _exiting;
@@ -543,12 +544,21 @@ public async Task<Results> CmdDetach()
543544

544545
public Task CmdBreakInternal()
545546
{
547+
<<<<<<< 17d1f39a11034234966c6bc4ddf9dc41d6c51d85
546548
this.VerifyNotDebuggingCoreDump();
547549

548550
// TODO May need to fix attach on windows.
549551
// Note that interrupt doesn't work when attached on OS X with gdb:
550552
// https://sourceware.org/bugzilla/show_bug.cgi?id=20035
551553
if (IsLocalGdb() && (PlatformUtilities.IsLinux() || PlatformUtilities.IsOSX()))
554+
=======
555+
if (ProcessState != ProcessState.Running)
556+
{
557+
return Task.CompletedTask;
558+
}
559+
//TODO May need to fix attach on windows and osx.
560+
if (IsLocalGdbAttach() && RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
561+
>>>>>>> Save per-thread forking state, interrupt over the pipe rat6her than using the mi
552562
{
553563
// for local linux debugging, send a signal to one of the debuggee processes rather than
554564
// using -exec-interrupt. -exec-interrupt does not work with attach and, in some instances, launch.
@@ -570,6 +580,13 @@ public Task CmdBreakInternal()
570580
return CmdUnixBreak(debuggeePid, ResultClass.done);
571581
}
572582
}
583+
else if (_transport is PipeTransport)
584+
{
585+
if (((PipeTransport)_transport).Interrupt(PidByInferior("i1")))
586+
{
587+
return Task.FromResult<Results>(new Results(ResultClass.done));
588+
}
589+
}
573590

574591
var res = CmdAsync("-exec-interrupt", ResultClass.done);
575592
return res.ContinueWith((t) =>
@@ -1140,6 +1157,7 @@ private void OnNotificationOutput(string cmd)
11401157
{
11411158
results = _miResults.ParseResultList(cmd.Substring("thread-group-exited,".Length));
11421159
HandleThreadGroupExited(results);
1160+
ThreadGroupExitedEvent(this, new ResultEventArgs(results, 0));
11431161
}
11441162
else if (cmd.StartsWith("thread-created,", StringComparison.Ordinal))
11451163
{
@@ -1230,21 +1248,31 @@ public uint InferiorByPid(int pid)
12301248
{
12311249
if ( grp.Value == pid)
12321250
{
1233-
// Inferior names are of the form "iX" where X in the inferior number
1234-
string name = grp.Key;
1235-
if (name[0] == 'i')
1236-
{
1237-
uint id;
1238-
if (UInt32.TryParse(name.Substring(1), out id))
1239-
{
1240-
return id;
1241-
}
1242-
}
1251+
return InferiorNumber(grp.Key);
12431252
}
12441253
}
12451254
return 0;
12461255
}
12471256

1257+
public int PidByInferior(string inf)
1258+
{
1259+
return _debuggeePids[inf];
1260+
}
1261+
1262+
public uint InferiorNumber(string groupId)
1263+
{
1264+
// Inferior names are of the form "iX" where X in the inferior number
1265+
if (groupId.Length >= 2 && groupId[0] == 'i')
1266+
{
1267+
uint id;
1268+
if (UInt32.TryParse(groupId.Substring(1), out id))
1269+
{
1270+
return id;
1271+
}
1272+
}
1273+
return 1; // default to the first inferior if group-id not understood
1274+
}
1275+
12481276
private void HandleThreadGroupExited(Results results)
12491277
{
12501278
string threadGroupId = results.TryFindString("id");

src/MICore/LaunchOptions.cs

Lines changed: 60 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -63,18 +63,19 @@ public enum LaunchCompleteCommand
6363
/// </summary>
6464
public sealed class PipeLaunchOptions : LaunchOptions
6565
{
66-
public PipeLaunchOptions(string PipePath, string PipeArguments)
66+
public PipeLaunchOptions(string PipePath, string PipeArguments, string PipeCommandArguments)
6767
{
6868
if (string.IsNullOrEmpty(PipePath))
6969
throw new ArgumentNullException("PipePath");
7070

7171
this.PipePath = PipePath;
7272
this.PipeArguments = PipeArguments;
73+
this.PipeCommandArguments = PipeCommandArguments;
7374
}
7475

7576
static internal PipeLaunchOptions CreateFromXml(Xml.LaunchOptions.PipeLaunchOptions source)
7677
{
77-
var options = new PipeLaunchOptions(RequireAttribute(source.PipePath, "PipePath"), source.PipeArguments);
78+
var options = new PipeLaunchOptions(RequireAttribute(source.PipePath, "PipePath"), source.PipeArguments, source.PipeCommandArguments);
7879
options.InitializeCommonOptions(source);
7980

8081
return options;
@@ -88,7 +89,13 @@ static internal PipeLaunchOptions CreateFromXml(Xml.LaunchOptions.PipeLaunchOpti
8889
/// <summary>
8990
/// [Optional] Arguments to pass to the pipe executable.
9091
/// </summary>
92+
///
9193
public string PipeArguments { get; private set; }
94+
95+
/// <summary>
96+
/// [Optional] Arguments to pass to the PipePath program that include a format specifier ('{0}') for a custom command.
97+
/// </summary>
98+
public string PipeCommandArguments { get; private set; }
9299
}
93100

94101
public sealed class TcpLaunchOptions : LaunchOptions
@@ -282,24 +289,6 @@ private static string ResolveFromPath(string command)
282289
/// </summary>
283290
public string MIDebuggerServerAddress { get; private set; }
284291

285-
/// <summary>
286-
/// [Required] Path to the executable file. This path must exist on the Visual Studio computer.
287-
/// </summary>
288-
public override string ExePath
289-
{
290-
get
291-
{
292-
return base.ExePath;
293-
}
294-
set
295-
{
296-
if (String.IsNullOrEmpty(value) || !LocalLaunchOptions.CheckPath(value))
297-
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, MICoreResources.Error_InvalidLocalExePath, value));
298-
299-
base.ExePath = value;
300-
}
301-
}
302-
303292
/// <summary>
304293
/// [Optional] List of environment variables to add to the launched process
305294
/// </summary>
@@ -397,12 +386,24 @@ public abstract class LaunchOptions
397386

398387
public MIMode DebuggerMIMode { get; set; }
399388

400-
private string _exePath;
401-
389+
private Xml.LaunchOptions.BaseLaunchOptions _baseOptions;
402390
/// <summary>
403391
/// Hold on to options in serializable form to support child process debugging
404392
/// </summary>
405-
public Xml.LaunchOptions.BaseLaunchOptions BaseOptions { get; set; }
393+
public Xml.LaunchOptions.BaseLaunchOptions BaseOptions
394+
{
395+
get { return _baseOptions; }
396+
protected set
397+
{
398+
if (value == null)
399+
throw new ArgumentNullException("BaseOptions");
400+
VerifyCanModifyProperty("BaseOptions");
401+
402+
_baseOptions = value;
403+
}
404+
}
405+
406+
private string _exePath;
406407

407408
/// <summary>
408409
/// [Required] Path to the executable file. This could be a path on the remote machine (for Pipe transport)
@@ -435,10 +436,20 @@ public string ExeArguments
435436
}
436437
}
437438

439+
private int _processId;
440+
438441
/// <summary>
439442
/// [Optional] If supplied, the debugger will attach to the process rather than launching a new one. Note that some operating systems will require admin rights to do this.
440443
/// </summary>
441-
public int ProcessId { get; set; }
444+
public int ProcessId
445+
{
446+
get { return _processId; }
447+
protected set
448+
{
449+
VerifyCanModifyProperty("ProcessId");
450+
_processId = value;
451+
}
452+
}
442453

443454
private string _coreDumpPath;
444455
/// <summary>
@@ -450,8 +461,10 @@ public string CoreDumpPath
450461
{
451462
return _coreDumpPath;
452463
}
453-
set
464+
protected set
454465
{
466+
VerifyCanModifyProperty("CoreDumpPath");
467+
455468
// CoreDumpPath is allowed to be null/empty
456469
_coreDumpPath = value;
457470
}
@@ -615,30 +628,40 @@ public LaunchCompleteCommand LaunchCompleteCommand
615628
}
616629
}
617630

618-
public bool DebugChildProcesses { get; set; }
631+
private bool _debugChildProcesses;
632+
633+
public bool DebugChildProcesses
634+
{
635+
get { return _debugChildProcesses; }
636+
protected set
637+
{
638+
VerifyCanModifyProperty("DebugChildProcesses");
639+
_debugChildProcesses = value;
640+
}
641+
}
619642

620-
public static string GetOptionsString(object o)
643+
public string GetOptionsString()
621644
{
622645
try
623646
{
624647
var strWriter = new StringWriter(CultureInfo.InvariantCulture);
625648
XmlSerializer serializer;
626649
using (XmlWriter writer = XmlWriter.Create(strWriter))
627650
{
628-
if (o is Xml.LaunchOptions.LocalLaunchOptions)
651+
if (BaseOptions is Xml.LaunchOptions.LocalLaunchOptions)
629652
{
630653
serializer = new XmlSerializer(typeof(Xml.LaunchOptions.LocalLaunchOptions));
631-
Serialize(serializer, writer, o);
654+
Serialize(serializer, writer, BaseOptions);
632655
}
633-
else if (o is Xml.LaunchOptions.PipeLaunchOptions)
656+
else if (BaseOptions is Xml.LaunchOptions.PipeLaunchOptions)
634657
{
635658
serializer = new XmlSerializer(typeof(Xml.LaunchOptions.PipeLaunchOptions));
636-
Serialize(serializer, writer, o);
659+
Serialize(serializer, writer, BaseOptions);
637660
}
638-
else if (o is Xml.LaunchOptions.TcpLaunchOptions)
661+
else if (BaseOptions is Xml.LaunchOptions.TcpLaunchOptions)
639662
{
640663
serializer = new XmlSerializer(typeof(Xml.LaunchOptions.TcpLaunchOptions));
641-
Serialize(serializer, writer, o);
664+
Serialize(serializer, writer, BaseOptions);
642665
}
643666
else
644667
{
@@ -835,7 +858,7 @@ public static object Deserialize(XmlSerializer serializer, XmlReader reader)
835858
}
836859
}
837860

838-
public static void Serialize(XmlSerializer serializer, XmlWriter writer, object o)
861+
private static void Serialize(XmlSerializer serializer, XmlWriter writer, object o)
839862
{
840863
try
841864
{
@@ -950,8 +973,11 @@ protected void InitializeCommonOptions(Xml.LaunchOptions.BaseLaunchOptions sourc
950973
else
951974
this.AdditionalSOLibSearchPath = string.Concat(this.AdditionalSOLibSearchPath, ";", additionalSOLibSearchPath);
952975
}
976+
<<<<<<< 17d1f39a11034234966c6bc4ddf9dc41d6c51d85
953977
if (string.IsNullOrEmpty(this.AbsolutePrefixSOLibSearchPath))
954978
this.AbsolutePrefixSOLibSearchPath = source.AbsolutePrefixSOLibSearchPath;
979+
=======
980+
>>>>>>> Save per-thread forking state, interrupt over the pipe rat6her than using the mi
955981

956982
this.ProcessId = source.ProcessId;
957983
this.CoreDumpPath = source.CoreDumpPath;

src/MICore/LaunchOptions.xsd

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,11 @@
290290
<xs:documentation>Any arguments to pass to this program.</xs:documentation>
291291
</xs:annotation>
292292
</xs:attribute>
293+
<xs:attribute name="PipeCommandArguments" type="xs:string" use="optional">
294+
<xs:annotation>
295+
<xs:documentation>Arguments to pass to the PipePath program that include a format specifier ('{0}') for a custom command.</xs:documentation>
296+
</xs:annotation>
297+
</xs:attribute>
293298
</xs:extension>
294299
</xs:complexContent>
295300
</xs:complexType>
@@ -320,7 +325,8 @@
320325
</xs:complexContent>
321326
</xs:complexType>
322327
</xs:element>
323-
<!--base type for LocalLaunchOptions, PipeLaunchOptions, and TcpLaunchOptions -->
328+
329+
<!--base type for LocalLaunchOptions, PipeLaunchOptions, and TcpLaunchOptions -->
324330
<xs:complexType name="BaseLaunchOptions">
325331
<xs:sequence>
326332
<xs:element name="SetupCommands" minOccurs="0" maxOccurs="1" type="CommandList">

src/MICore/LaunchOptions.xsd.types.designer.cs

Lines changed: 4 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)