Skip to content

Commit ceb42af

Browse files
authored
Make attachdebugger flag work on non-Windows (#79499)
These compiler flags used Debugger.Launch, which only works on windows. I borrowed the equivalent code from the LSP launcher, which already has this functionality (https://github.com/dotnet/roslyn/blob/cf34acbc5d0f64ff87013cdd02ae61cff562daaf/src/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs#L75-L89).
1 parent 27b63ab commit ceb42af

File tree

3 files changed

+62
-2
lines changed

3 files changed

+62
-2
lines changed

src/Compilers/CSharp/Portable/CommandLine/CSharpCommandLineParser.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
using System.Globalization;
1010
using System.IO;
1111
using System.Linq;
12+
using System.Runtime.InteropServices;
1213
using System.Security.Cryptography;
1314
using System.Text;
15+
using System.Threading;
1416
using Microsoft.CodeAnalysis.Emit;
1517
using Microsoft.CodeAnalysis.PooledObjects;
1618
using Microsoft.CodeAnalysis.Text;
@@ -282,7 +284,22 @@ internal sealed override CommandLineArguments CommonParse(IEnumerable<string> ar
282284

283285
#if DEBUG
284286
case "attachdebugger":
285-
Debugger.Launch();
287+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
288+
{
289+
// Debugger.Launch() only works on Windows.
290+
_ = Debugger.Launch();
291+
}
292+
else
293+
{
294+
var timeout = TimeSpan.FromMinutes(2);
295+
Console.WriteLine($"Compiler started with process ID {Environment.ProcessId}");
296+
Console.WriteLine($"Waiting {timeout:g} for a debugger to attach");
297+
using var timeoutSource = new CancellationTokenSource(timeout);
298+
while (!Debugger.IsAttached && !timeoutSource.Token.IsCancellationRequested)
299+
{
300+
Thread.Sleep(100);
301+
}
302+
}
286303
continue;
287304
#endif
288305
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
7+
namespace Microsoft.CodeAnalysis.CSharp;
8+
9+
internal static class EnvironmentExtensions
10+
{
11+
extension(Environment)
12+
{
13+
public static int ProcessId
14+
{
15+
get
16+
{
17+
#if NET
18+
return Environment.ProcessId;
19+
#else
20+
return System.Diagnostics.Process.GetCurrentProcess().Id;
21+
#endif
22+
}
23+
}
24+
}
25+
}

src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Imports System.IO
88
Imports System.Runtime.InteropServices
99
Imports System.Security.Cryptography
1010
Imports System.Text
11+
Imports System.Threading
1112
Imports Microsoft.CodeAnalysis.Collections
1213
Imports Microsoft.CodeAnalysis.Emit
1314
Imports Microsoft.CodeAnalysis.PooledObjects
@@ -446,7 +447,24 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
446447

447448
#If DEBUG Then
448449
Case "attachdebugger"
449-
Debugger.Launch()
450+
If RuntimeInformation.IsOSPlatform(OSPlatform.Windows) Then
451+
' Debugger.Launch() only works on Windows
452+
Debugger.Launch()
453+
Else
454+
Dim timeout = TimeSpan.FromMinutes(2)
455+
#If NET Then
456+
Dim processId = Environment.ProcessId
457+
#Else
458+
Dim processId = System.Diagnostics.Process.GetCurrentProcess().Id
459+
#End If
460+
Console.WriteLine($"Compiler started with process ID {processId}")
461+
Console.WriteLine($"Waiting {timeout:g} for a debugger to attach")
462+
Using timeoutSource = New CancellationTokenSource(timeout)
463+
While Not Debugger.IsAttached AndAlso Not timeoutSource.Token.IsCancellationRequested
464+
Thread.Sleep(100)
465+
End While
466+
End Using
467+
End If
450468
Continue For
451469
#End If
452470
End Select

0 commit comments

Comments
 (0)