Skip to content

Commit 52609f4

Browse files
committed
fix(ci): address cross-platform test races and Windows GCC toolchain flags
- Separate stderr in ScriptRunExecutor and prioritize for diagnostic parsing - Make PythonTracebackParser summary and frames resilient to interleaved lines - Differentiate GCC from Clang when adding Windows SDK flags in CppBuildAndRunScriptRunner (-imsvc is clang-only) - Add -lws2_32 on Windows for GCC/Clang in CppBuildAndRunScriptRunner and CppNotebookKernel - Record traffic log before closing response in FryHttpListenerServerEngine and add resilient poll wait in HttpServerEngineTests
1 parent a8288fa commit 52609f4

6 files changed

Lines changed: 56 additions & 13 deletions

File tree

‎Services/Languages/Cpp/CppBuildAndRunScriptRunner.cs‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ public async Task<ScriptRunPlan> PlanAsync(ScriptRunContext context, Cancellatio
1515
var compilerPath = context.Toolchain.ExecutablePath;
1616
var fileName = Path.GetFileName(compilerPath.Replace('\\', '/'));
1717
var isCl = fileName.Equals("cl.exe", StringComparison.OrdinalIgnoreCase) || fileName.Equals("cl", StringComparison.OrdinalIgnoreCase);
18+
var isClang = fileName.Contains("clang", StringComparison.OrdinalIgnoreCase);
1819

1920
var normalizedSource = context.SourceFilePath.Replace('\\', '/');
2021
var fileBaseName = Path.GetFileNameWithoutExtension(normalizedSource);
@@ -77,15 +78,15 @@ public async Task<ScriptRunPlan> PlanAsync(ScriptRunContext context, Cancellatio
7778

7879
if (host.IsWindows && windowsSdk != null)
7980
{
80-
if (windowsSdk.HasMsvcHeaders)
81+
if (isClang && windowsSdk.HasMsvcHeaders)
8182
{
8283
foreach (var inc in windowsSdk.IncludeDirectories)
8384
{
8485
compileArgs.Add("-imsvc");
8586
compileArgs.Add(inc);
8687
}
8788
}
88-
else if (windowsSdk.HasMinGw)
89+
else if (isClang && windowsSdk.HasMinGw)
8990
{
9091
compileArgs.Add("--target=x86_64-w64-windows-gnu");
9192
compileArgs.Add($"--sysroot={windowsSdk.MinGwSysroot}");
@@ -104,6 +105,10 @@ public async Task<ScriptRunPlan> PlanAsync(ScriptRunContext context, Cancellatio
104105
compileArgs.Add("-o");
105106
compileArgs.Add(binPath);
106107
compileArgs.Add(context.SourceFilePath);
108+
if (host.IsWindows)
109+
{
110+
compileArgs.Add("-lws2_32");
111+
}
107112
}
108113

109114
var environment = await CppProcessEnvironment.ForAsync(host, context.Toolchain, ct);

‎Services/Languages/Cpp/CppNotebookKernel.cs‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,10 @@ public async Task<KernelExecutionResult> ExecuteAsync(KernelExecutionRequest req
121121
compileArgs.Add("-o");
122122
compileArgs.Add(binPath);
123123
compileArgs.Add(sourcePath);
124+
if (_host.IsWindows)
125+
{
126+
compileArgs.Add("-lws2_32");
127+
}
124128
}
125129

126130
var compileResult = await _host.RunAsync(compilerPath, compileArgs, TimeSpan.FromSeconds(30), ct).ConfigureAwait(false);

‎Services/Languages/Python/PythonTracebackParser.cs‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,12 @@ private static int FindExceptionSummary(List<Line> lines)
120120
for (var j = i - 1; j >= 0; j--)
121121
{
122122
if (FrameLine().IsMatch(lines[j].Text)) return i;
123-
if (lines[j].Indent == 0 && lines[j].Text.Length > 0 && !IsHeading(lines[j].Text)) break;
123+
if (lines[j].Indent == 0 && (lines[j].Text.StartsWith("During handling", StringComparison.Ordinal) ||
124+
lines[j].Text.StartsWith("The above exception", StringComparison.Ordinal) ||
125+
(ExceptionLine().IsMatch(lines[j].Text) && LooksLikeExceptionName(lines[j].Text))))
126+
{
127+
break;
128+
}
124129
}
125130
}
126131

@@ -152,7 +157,9 @@ private static List<Frame> FramesOf(List<Line> lines, int summaryIndex)
152157
{
153158
frames.Add(new Frame(frame.Groups["file"].Value, number, i));
154159
}
155-
else if (line.Indent == 0 && line.Text.Length > 0)
160+
else if (line.Indent == 0 && (line.Text.StartsWith("During handling", StringComparison.Ordinal) ||
161+
line.Text.StartsWith("The above exception", StringComparison.Ordinal) ||
162+
(ExceptionLine().IsMatch(line.Text) && LooksLikeExceptionName(line.Text))))
156163
{
157164
break; // the end of an earlier, chained traceback
158165
}

‎Services/Processes/ScriptRunExecutor.cs‎

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,16 +138,23 @@ private async Task<ScriptRunResult> RunStepsAsync(
138138

139139
var step = plan.Steps[i];
140140
var tail = new OutputTail(OutputTailLength);
141+
var errorTail = new OutputTail(OutputTailLength);
141142
void Receive(string text)
142143
{
143144
tail.Append(text);
144145
onOutput(text);
145146
}
147+
void ReceiveError(string text)
148+
{
149+
tail.Append(text);
150+
errorTail.Append(text);
151+
onOutput(text);
152+
}
146153

147154
IManagedProcess process;
148155
try
149156
{
150-
process = _launcher.Start(step.IsBuildStep ? step.Spec : WithEnvironment(step.Spec, environment), Receive, Receive);
157+
process = _launcher.Start(step.IsBuildStep ? step.Spec : WithEnvironment(step.Spec, environment), Receive, ReceiveError);
151158
}
152159
catch (ProcessStartException ex)
153160
{
@@ -168,9 +175,22 @@ void Receive(string text)
168175
if (cts.IsCancellationRequested) return new ScriptRunResult(exitCode, true, clock.Elapsed, DiagnosticParseResult.Empty);
169176

170177
// Only a failed step is read for errors: a successful run can print text that merely looks like one.
171-
var diagnostics = exitCode != 0 && parser != null
172-
? parser.Parse(tail.ToString(), sourceFilePath)
173-
: DiagnosticParseResult.Empty;
178+
// Standard error is prioritized because compilers and interpreters write tracebacks and errors there,
179+
// avoiding interleaving with standard output.
180+
var diagnostics = DiagnosticParseResult.Empty;
181+
if (exitCode != 0 && parser != null)
182+
{
183+
var errorOutput = errorTail.ToString();
184+
if (!string.IsNullOrWhiteSpace(errorOutput))
185+
{
186+
diagnostics = parser.Parse(errorOutput, sourceFilePath);
187+
}
188+
189+
if (diagnostics.Diagnostics.Count == 0 && diagnostics.MissingDependency == null)
190+
{
191+
diagnostics = parser.Parse(tail.ToString(), sourceFilePath);
192+
}
193+
}
174194

175195
if (step.IsBuildStep && exitCode != 0)
176196
{

‎Services/Server/FryHttpListenerServerEngine.cs‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -313,11 +313,6 @@ private async Task HandleRequestAsync(HttpListenerContext httpContext, Cancellat
313313
}
314314
catch { }
315315
}
316-
finally
317-
{
318-
try { response.Close(); } catch { }
319-
}
320-
321316
sw.Stop();
322317
Interlocked.Increment(ref _totalRequestsServed);
323318

@@ -341,6 +336,12 @@ private async Task HandleRequestAsync(HttpListenerContext httpContext, Cancellat
341336
}
342337

343338
RecordTraffic(logItem);
339+
340+
try
341+
{
342+
response.Close();
343+
}
344+
catch { }
344345
}
345346

346347
public async Task<IServerResult> ExecuteLoopbackTestAsync(FryServerCellItem cell, FryServerTestHarnessItem testHarness, CancellationToken cancellationToken = default)

‎Tests/Server/HttpServerEngineTests.cs‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,12 @@ public async Task ServerEngine_EndToEnd_ServesExternalHttpRequest()
7373
Assert.True(parsed.RootElement.GetProperty("hasOrders").GetBoolean());
7474
Assert.Equal("FryServer", parsed.RootElement.GetProperty("appName").GetString());
7575

76+
var deadline = DateTime.UtcNow.AddSeconds(5);
77+
while (engine.TrafficLog.Count == 0 && DateTime.UtcNow < deadline)
78+
{
79+
await Task.Delay(20);
80+
}
81+
7682
Assert.True(engine.TotalRequestsServed >= 1);
7783
Assert.NotEmpty(engine.TrafficLog);
7884
}

0 commit comments

Comments
 (0)