Skip to content

Commit

Permalink
Adapt explicit disposal of volatile processes to Azure Pipelines
Browse files Browse the repository at this point in the history
With the previous version, Azure Pipeline sometimes failed the execution of the tests, not completing the test step.
Looking into these failures, I also found the following message in the logs from Azure Pipelines:

> The STDIO streams did not close within 10 seconds of the exit event from process 'C:\hostedtoolcache\windows\dotnet\dotnet.exe'. This may indicate a child process inherited the STDIO streams and has not yet exited.

For discussions of the problem, see also:

+ microsoft/azure-pipelines-tasks#17548
+ microsoft/azure-pipelines-tasks#13033
+ microsoft/azure-pipelines-tasks#18476
  • Loading branch information
Viir committed Jul 2, 2023
1 parent 0480879 commit b017631
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 10 deletions.
34 changes: 27 additions & 7 deletions implement/elm-time/Pine/VolatileProcessNative.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ public record ReadAllFromNativeProcess(

private readonly ConcurrentQueue<ReadOnlyMemory<byte>> stdErrQueue = new();

private readonly CancellationTokenSource disposedCancellationTokenSource = new();

public VolatileProcessNative(
Func<byte[], byte[]?>? getFileFromHashSHA256,
ElmTime.Platform.WebService.InterfaceToHost.CreateVolatileProcessNativeStruct createRequest)
Expand Down Expand Up @@ -70,8 +72,15 @@ public record ReadAllFromNativeProcess(

process.Start();

Task.Run(() => ReadFromStreamToQueue(stdOutQueue, process.StandardOutput.BaseStream));
Task.Run(() => ReadFromStreamToQueue(stdErrQueue, process.StandardError.BaseStream));
Task.Run(() => ReadFromStreamToQueueLoopAsync(
stdOutQueue,
process.StandardOutput.BaseStream,
cancellationToken: disposedCancellationTokenSource.Token));

Task.Run(() => ReadFromStreamToQueueLoopAsync(
stdErrQueue,
process.StandardError.BaseStream,
cancellationToken: disposedCancellationTokenSource.Token));
}

public void WriteToStdIn(ReadOnlyMemory<byte> data)
Expand Down Expand Up @@ -111,17 +120,25 @@ public static ReadOnlyMemory<byte> ReadAllFromStream(Stream stream)
return CommonConversion.Concat(buffers);
}

public static long ReadFromStreamToQueue(ConcurrentQueue<ReadOnlyMemory<byte>> queue, Stream stream)
public static async Task<long> ReadFromStreamToQueueLoopAsync(
ConcurrentQueue<ReadOnlyMemory<byte>> queue,
Stream stream,
CancellationToken cancellationToken)
{
long aggregateBytesRead = 0;

try
{
while (true)
while (!cancellationToken.IsCancellationRequested)
{
var buffer = new byte[0x10_000];
var buffer = new byte[0x100_000];

var bytesRead = stream.ReadAtLeast(buffer, minimumBytes: 1, throwOnEndOfStream: true);
var bytesRead =
await stream.ReadAtLeastAsync(
buffer,
minimumBytes: 1,
throwOnEndOfStream: true,
cancellationToken: cancellationToken);

if (bytesRead == 0)
continue;
Expand All @@ -133,14 +150,17 @@ public static long ReadFromStreamToQueue(ConcurrentQueue<ReadOnlyMemory<byte>> q
}
catch (EndOfStreamException)
{
return aggregateBytesRead;
}

return aggregateBytesRead;
}

public void Dispose()
{
try
{
disposedCancellationTokenSource.Cancel();

if (process is not null && !process.HasExited)
process.Kill();

Expand Down
12 changes: 12 additions & 0 deletions implement/elm-time/Platform/WebService/PublicAppState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ public class PublicAppState
{
applicationStoppingCancellationTokenSource.Cancel();
app.Logger?.LogInformation("Public app noticed ApplicationStopping.");
DisposeAsync().Wait();
});

app.UseResponseCompression();
Expand All @@ -151,6 +152,17 @@ public class PublicAppState
return app;
}

async System.Threading.Tasks.Task DisposeAsync()
{
await
System.Threading.Tasks.Task.WhenAll(
volatileProcesses.Select(kvp =>
System.Threading.Tasks.Task.Run(() =>
{
(kvp.Value as IDisposable)?.Dispose();
})));
}

private void ConfigureServices(
IServiceCollection services,
ILogger logger)
Expand Down
2 changes: 1 addition & 1 deletion implement/elm-time/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace ElmTime;

public class Program
{
public static string AppVersionId => "2023-06-30";
public static string AppVersionId => "2023-07-01";

private static int AdminInterfaceDefaultPort => 4000;

Expand Down
4 changes: 2 additions & 2 deletions implement/elm-time/elm-time.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
<TargetFramework>net7.0</TargetFramework>
<RootNamespace>ElmTime</RootNamespace>
<AssemblyName>elm-time</AssemblyName>
<AssemblyVersion>2023.0630.0.0</AssemblyVersion>
<FileVersion>2023.0630.0.0</FileVersion>
<AssemblyVersion>2023.0701.0.0</AssemblyVersion>
<FileVersion>2023.0701.0.0</FileVersion>
<Nullable>enable</Nullable>
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>
</PropertyGroup>
Expand Down

0 comments on commit b017631

Please sign in to comment.