FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Wait for debugger flag for .NET Core 2.0 / 2.1 implementation (#130) · sdscgithub/docker-lambda@26f9f37 · GitHub

Commit 26f9f37

Browse files
authored andcommitted
Wait for debugger flag for .NET Core 2.0 / 2.1 implementation (lambci#130)
* Implement wait for debugger flag * Simplify flag finding. Remove environemnt variable. * Remove displaying process id, as it turned out to be not useful * Revert default event body to empty object * Update name of debugger flag to avoid future clashing
1 parent b55522a commit 26f9f37

4 files changed

Lines changed: 240 additions & 62 deletions

File tree

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using System;
2+
using System.Diagnostics;
3+
using System.Threading.Tasks;
4+
5+
namespace MockLambdaRuntime
6+
{
7+
internal static class DebuggerExtensions
8+
{
9+
/// <summary>
10+
/// Tries to wait for the debugger to attach by inspecting <see cref="Debugger.IsAttached"/> property in a loop.
11+
/// </summary>
12+
/// <param name="queryInterval"><see cref="TimeSpan"/> representing the frequency of inspection.</param>
13+
/// <param name="timeout"><see cref="TimeSpan"/> representing the timeout for the operation.</param>
14+
/// <returns><c>True</c> if debugger was attached, false if timeout occured.</returns>
15+
public static bool TryWaitForAttaching(TimeSpan queryInterval, TimeSpan timeout)
16+
{
17+
var stopwatch = Stopwatch.StartNew();
18+
19+
while (!Debugger.IsAttached)
20+
{
21+
if (stopwatch.Elapsed > timeout)
22+
{
23+
return false;
24+
}
25+
26+
Task.Delay(queryInterval).Wait();
27+
}
28+
29+
return true;
30+
}
31+
}
32+
}

‎dotnetcore2.0/run/MockBootstraps/Program.cs‎

Lines changed: 88 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.IO;
34
using System.Reflection;
45
using System.Runtime.Loader;
@@ -9,50 +10,79 @@ namespace MockLambdaRuntime
910
{
1011
class Program
1112
{
13+
private const string WaitForDebuggerFlag = "--debugger-spin-wait";
14+
private const bool WaitForDebuggerFlagDefaultValue = false;
15+
1216
/// Task root of lambda task
1317
static string lambdaTaskRoot = EnvHelper.GetOrDefault("LAMBDA_TASK_ROOT", "/var/task");
1418

19+
private static readonly TimeSpan _debuggerStatusQueryInterval = TimeSpan.FromMilliseconds(50);
20+
private static readonly TimeSpan _debuggerStatusQueryTimeout = TimeSpan.FromMinutes(10);
21+
1522
/// Program entry point
1623
static void Main(string[] args)
1724
{
1825
AssemblyLoadContext.Default.Resolving += OnAssemblyResolving;
1926

20-
var handler = GetFunctionHandler(args);
21-
var body = GetEventBody(args);
22-
23-
var lambdaContext = new MockLambdaContext(handler, body);
24-
25-
var userCodeLoader = new UserCodeLoader(handler, InternalLogger.NO_OP_LOGGER);
26-
userCodeLoader.Init(Console.Error.WriteLine);
27-
28-
var lambdaContextInternal = new LambdaContextInternal(lambdaContext.RemainingTime,
29-
LogAction, new Lazy<CognitoClientContextInternal>(),
30-
lambdaContext.RequestId,
31-
new Lazy<string>(lambdaContext.Arn),
32-
new Lazy<string>(string.Empty),
33-
new Lazy<string>(string.Empty),
34-
Environment.GetEnvironmentVariables());
35-
36-
Exception lambdaException = null;
37-
38-
LogRequestStart(lambdaContext);
3927
try
4028
{
41-
userCodeLoader.Invoke(lambdaContext.InputStream, lambdaContext.OutputStream, lambdaContextInternal);
29+
var shouldWaitForDebugger = GetShouldWaitForDebuggerFlag(args, out var positionalArgs);
30+
31+
var handler = GetFunctionHandler(positionalArgs);
32+
var body = GetEventBody(positionalArgs);
33+
34+
if (shouldWaitForDebugger)
35+
{
36+
Console.Error.WriteLine("Waiting for the debugger to attach...");
37+
38+
if (!DebuggerExtensions.TryWaitForAttaching(
39+
_debuggerStatusQueryInterval,
40+
_debuggerStatusQueryTimeout))
41+
{
42+
Console.Error.WriteLine("Timeout. Proceeding without debugger.");
43+
}
44+
}
45+
46+
var lambdaContext = new MockLambdaContext(handler, body);
47+
48+
var userCodeLoader = new UserCodeLoader(handler, InternalLogger.NO_OP_LOGGER);
49+
userCodeLoader.Init(Console.Error.WriteLine);
50+
51+
var lambdaContextInternal = new LambdaContextInternal(lambdaContext.RemainingTime,
52+
LogAction, new Lazy<CognitoClientContextInternal>(),
53+
lambdaContext.RequestId,
54+
new Lazy<string>(lambdaContext.Arn),
55+
new Lazy<string>(string.Empty),
56+
new Lazy<string>(string.Empty),
57+
Environment.GetEnvironmentVariables());
58+
59+
Exception lambdaException = null;
60+
61+
LogRequestStart(lambdaContext);
62+
try
63+
{
64+
userCodeLoader.Invoke(lambdaContext.InputStream, lambdaContext.OutputStream, lambdaContextInternal);
65+
}
66+
catch (Exception ex)
67+
{
68+
lambdaException = ex;
69+
}
70+
LogRequestEnd(lambdaContext);
71+
72+
if (lambdaException == null)
73+
{
74+
Console.WriteLine(lambdaContext.OutputText);
75+
}
76+
else
77+
{
78+
Console.Error.WriteLine(lambdaException);
79+
}
4280
}
43-
catch (Exception ex)
44-
{
45-
lambdaException = ex;
46-
}
47-
LogRequestEnd(lambdaContext);
4881

49-
if (lambdaException == null)
50-
{
51-
Console.WriteLine(lambdaContext.OutputText);
52-
}
53-
else
82+
// Catch all unhandled exceptions from runtime, to prevent user from hanging on them while debugging
83+
catch (Exception ex)
5484
{
55-
Console.Error.WriteLine(lambdaException);
85+
Console.Error.WriteLine($"\nUnhandled exception occured in runner:\n{ex}");
5686
}
5787
}
5888

@@ -68,6 +98,33 @@ private static void LogAction(string text)
6898
Console.Error.WriteLine(text);
6999
}
70100

101+
/// <summary>
102+
/// Extracts "waitForDebugger" flag from args. Returns other unprocessed arguments.
103+
/// </summary>
104+
/// <param name="args">Args to look through</param>
105+
/// <param name="unprocessed">Arguments except for the "waitForDebugger" ones</param>
106+
/// <returns>"waitForDebugger" flag value</returns>
107+
private static bool GetShouldWaitForDebuggerFlag(string[] args, out string[] unprocessed)
108+
{
109+
var flagValue = WaitForDebuggerFlagDefaultValue;
110+
111+
var unprocessedList = new List<string>();
112+
113+
foreach (var argument in args)
114+
{
115+
if (argument == WaitForDebuggerFlag)
116+
{
117+
flagValue = true;
118+
continue;
119+
}
120+
121+
unprocessedList.Add(argument);
122+
}
123+
124+
unprocessed = unprocessedList.ToArray();
125+
return flagValue;
126+
}
127+
71128
static void LogRequestStart(MockLambdaContext context)
72129
{
73130
Console.Error.WriteLine($"START RequestId: {context.RequestId} Version: {context.FunctionVersion}");
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using System;
2+
using System.Diagnostics;
3+
using System.Threading.Tasks;
4+
5+
namespace MockLambdaRuntime
6+
{
7+
internal static class DebuggerExtensions
8+
{
9+
/// <summary>
10+
/// Tries to wait for the debugger to attach by inspecting <see cref="Debugger.IsAttached"/> property in a loop.
11+
/// </summary>
12+
/// <param name="queryInterval"><see cref="TimeSpan"/> representing the frequency of inspection.</param>
13+
/// <param name="timeout"><see cref="TimeSpan"/> representing the timeout for the operation.</param>
14+
/// <returns><c>True</c> if debugger was attached, false if timeout occured.</returns>
15+
public static bool TryWaitForAttaching(TimeSpan queryInterval, TimeSpan timeout)
16+
{
17+
var stopwatch = Stopwatch.StartNew();
18+
19+
while (!Debugger.IsAttached)
20+
{
21+
if (stopwatch.Elapsed > timeout)
22+
{
23+
return false;
24+
}
25+
26+
Task.Delay(queryInterval).Wait();
27+
}
28+
29+
return true;
30+
}
31+
}
32+
}

‎dotnetcore2.1/run/MockBootstraps/Program.cs‎

Lines changed: 88 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.IO;
34
using System.Reflection;
45
using System.Runtime.Loader;
@@ -9,50 +10,79 @@ namespace MockLambdaRuntime
910
{
1011
class Program
1112
{
13+
private const string WaitForDebuggerFlag = "--debugger-spin-wait";
14+
private const bool WaitForDebuggerFlagDefaultValue = false;
15+
1216
/// Task root of lambda task
1317
static string lambdaTaskRoot = EnvHelper.GetOrDefault("LAMBDA_TASK_ROOT", "/var/task");
1418

19+
private static readonly TimeSpan _debuggerStatusQueryInterval = TimeSpan.FromMilliseconds(50);
20+
private static readonly TimeSpan _debuggerStatusQueryTimeout = TimeSpan.FromMinutes(10);
21+
1522
/// Program entry point
1623
static void Main(string[] args)
1724
{
1825
AssemblyLoadContext.Default.Resolving += OnAssemblyResolving;
1926

20-
var handler = GetFunctionHandler(args);
21-
var body = GetEventBody(args);
22-
23-
var lambdaContext = new MockLambdaContext(handler, body);
24-
25-
var userCodeLoader = new UserCodeLoader(handler, InternalLogger.NO_OP_LOGGER);
26-
userCodeLoader.Init(Console.Error.WriteLine);
27-
28-
var lambdaContextInternal = new LambdaContextInternal(lambdaContext.RemainingTime,
29-
LogAction, new Lazy<CognitoClientContextInternal>(),
30-
lambdaContext.RequestId,
31-
new Lazy<string>(lambdaContext.Arn),
32-
new Lazy<string>(string.Empty),
33-
new Lazy<string>(string.Empty),
34-
Environment.GetEnvironmentVariables());
35-
36-
Exception lambdaException = null;
37-
38-
LogRequestStart(lambdaContext);
3927
try
4028
{
41-
userCodeLoader.Invoke(lambdaContext.InputStream, lambdaContext.OutputStream, lambdaContextInternal);
29+
var shouldWaitForDebugger = GetShouldWaitForDebuggerFlag(args, out var positionalArgs);
30+
31+
var handler = GetFunctionHandler(positionalArgs);
32+
var body = GetEventBody(positionalArgs);
33+
34+
if (shouldWaitForDebugger)
35+
{
36+
Console.Error.WriteLine("Waiting for the debugger to attach...");
37+
38+
if (!DebuggerExtensions.TryWaitForAttaching(
39+
_debuggerStatusQueryInterval,
40+
_debuggerStatusQueryTimeout))
41+
{
42+
Console.Error.WriteLine("Timeout. Proceeding without debugger.");
43+
}
44+
}
45+
46+
var lambdaContext = new MockLambdaContext(handler, body);
47+
48+
var userCodeLoader = new UserCodeLoader(handler, InternalLogger.NO_OP_LOGGER);
49+
userCodeLoader.Init(Console.Error.WriteLine);
50+
51+
var lambdaContextInternal = new LambdaContextInternal(lambdaContext.RemainingTime,
52+
LogAction, new Lazy<CognitoClientContextInternal>(),
53+
lambdaContext.RequestId,
54+
new Lazy<string>(lambdaContext.Arn),
55+
new Lazy<string>(string.Empty),
56+
new Lazy<string>(string.Empty),
57+
Environment.GetEnvironmentVariables());
58+
59+
Exception lambdaException = null;
60+
61+
LogRequestStart(lambdaContext);
62+
try
63+
{
64+
userCodeLoader.Invoke(lambdaContext.InputStream, lambdaContext.OutputStream, lambdaContextInternal);
65+
}
66+
catch (Exception ex)
67+
{
68+
lambdaException = ex;
69+
}
70+
LogRequestEnd(lambdaContext);
71+
72+
if (lambdaException == null)
73+
{
74+
Console.WriteLine(lambdaContext.OutputText);
75+
}
76+
else
77+
{
78+
Console.Error.WriteLine(lambdaException);
79+
}
4280
}
43-
catch (Exception ex)
44-
{
45-
lambdaException = ex;
46-
}
47-
LogRequestEnd(lambdaContext);
4881

49-
if (lambdaException == null)
50-
{
51-
Console.WriteLine(lambdaContext.OutputText);
52-
}
53-
else
82+
// Catch all unhandled exceptions from runtime, to prevent user from hanging on them while debugging
83+
catch (Exception ex)
5484
{
55-
Console.Error.WriteLine(lambdaException);
85+
Console.Error.WriteLine($"\nUnhandled exception occured in runner:\n{ex}");
5686
}
5787
}
5888

@@ -68,6 +98,33 @@ private static void LogAction(string text)
6898
Console.Error.WriteLine(text);
6999
}
70100

101+
/// <summary>
102+
/// Extracts "waitForDebugger" flag from args. Returns other unprocessed arguments.
103+
/// </summary>
104+
/// <param name="args">Args to look through</param>
105+
/// <param name="unprocessed">Arguments except for the "waitForDebugger" ones</param>
106+
/// <returns>"waitForDebugger" flag value</returns>
107+
private static bool GetShouldWaitForDebuggerFlag(string[] args, out string[] unprocessed)
108+
{
109+
var flagValue = WaitForDebuggerFlagDefaultValue;
110+
111+
var unprocessedList = new List<string>();
112+
113+
foreach (var argument in args)
114+
{
115+
if (argument == WaitForDebuggerFlag)
116+
{
117+
flagValue = true;
118+
continue;
119+
}
120+
121+
unprocessedList.Add(argument);
122+
}
123+
124+
unprocessed = unprocessedList.ToArray();
125+
return flagValue;
126+
}
127+
71128
static void LogRequestStart(MockLambdaContext context)
72129
{
73130
Console.Error.WriteLine($"START RequestId: {context.RequestId} Version: {context.FunctionVersion}");

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL