2
0

Fix DDC/CI timeout using Task.WhenAny
Some checks failed
Build / build (push) Has been cancelled
Build and Release / build (push) Has been cancelled

Previous timeout using CancellationToken didn't work because
ReadToEndAsync blocks waiting for process output. Now using
Task.WhenAny with Task.Delay to properly timeout and kill
hung processes after 5 seconds.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-07 11:57:13 -05:00
parent 77e9b0505a
commit af8b09cfa2
2 changed files with 26 additions and 22 deletions

View File

@@ -13,9 +13,9 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<Version>1.0.13</Version> <Version>1.0.14</Version>
<AssemblyVersion>1.0.13.0</AssemblyVersion> <AssemblyVersion>1.0.14.0</AssemblyVersion>
<FileVersion>1.0.13.0</FileVersion> <FileVersion>1.0.14.0</FileVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -28,18 +28,17 @@ internal class ConsoleHelper
p.StartInfo.FileName = command; p.StartInfo.FileName = command;
p.Start(); p.Start();
using var cts = new CancellationTokenSource(timeoutMs); var readTask = p.StandardOutput.ReadToEndAsync();
try var completedTask = await Task.WhenAny(readTask, Task.Delay(timeoutMs));
if (completedTask != readTask)
{ {
var output = await p.StandardOutput.ReadToEndAsync(cts.Token); // Timeout - kill the process
await p.WaitForExitAsync(cts.Token); try { p.Kill(true); } catch { }
return output;
}
catch (OperationCanceledException)
{
try { p.Kill(); } catch { }
return string.Empty; return string.Empty;
} }
return await readTask;
} }
public static async Task<string> CmdCommandAsync(params string[] cmds) => public static async Task<string> CmdCommandAsync(params string[] cmds) =>
@@ -63,23 +62,28 @@ internal class ConsoleHelper
} }
p.StandardInput.WriteLine("exit"); p.StandardInput.WriteLine("exit");
using var cts = new CancellationTokenSource(timeoutMs); var readTask = Task.Run(async () =>
try
{ {
var result = await p.StandardOutput.ReadToEndAsync(cts.Token); var result = await p.StandardOutput.ReadToEndAsync();
var error = await p.StandardError.ReadToEndAsync(cts.Token); var error = await p.StandardError.ReadToEndAsync();
if (!string.IsNullOrWhiteSpace(error)) if (!string.IsNullOrWhiteSpace(error))
result = result + "\r\n<Error Message>:\r\n" + error; result = result + "\r\n<Error Message>:\r\n" + error;
await p.WaitForExitAsync(cts.Token);
p.Close();
Debug.WriteLine(result);
return result; return result;
} });
catch (OperationCanceledException)
var completedTask = await Task.WhenAny(readTask, Task.Delay(timeoutMs));
if (completedTask != readTask)
{ {
try { p.Kill(); } catch { } // Timeout - kill the process
try { p.Kill(true); } catch { }
return string.Empty; return string.Empty;
} }
var output = await readTask;
p.Close();
Debug.WriteLine(output);
return output;
} }
public static string Command(string fileName, params string[] cmds) public static string Command(string fileName, params string[] cmds)