Skip to content

Commit 13e3994

Browse files
Zaid-Ajajjulienp
andauthored
Fix program hanging when a resource transformation throws an exception (pulumi#307)
Fixes pulumi#291 Fixes pulumi#174 (duplicate of the former) The problem is that the task that is created for logging the exception never resolves. Simplified to use `Task.Run(...)` without `Task.ContinueWith(...)` and added an integration test to verify that a failing transformation actually exits the program without hanging. --------- Co-authored-by: Julien <[email protected]>
1 parent 9e951d4 commit 13e3994

File tree

7 files changed

+71
-3
lines changed

7 files changed

+71
-3
lines changed
+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
component: sdk
2+
kind: Bug Fixes
3+
body: Fix program hanging when a resource transformation throws an exception
4+
time: 2024-07-25T19:03:20.914101+02:00
5+
custom:
6+
PR: "307"

.github/workflows/pr.yml

+2
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ jobs:
146146
run: dotnet run integration test TestDeletedWith
147147
- name: TestDotNetTransforms
148148
run: dotnet run integration test TestDotNetTransforms
149+
- name: TestFailingTransfomationExitsProgram
150+
run: dotnet run integration test TestFailingTransfomationExitsProgram
149151

150152
info:
151153
name: gather
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using Pulumi;
2+
using System.Threading.Tasks;
3+
4+
class ComponentArgs : ResourceArgs { }
5+
6+
class Component : ComponentResource
7+
{
8+
public Component(string name, ComponentArgs args, ComponentResourceOptions? options = null) : base("test:index:Component", name, args, options)
9+
{
10+
}
11+
}
12+
13+
class MyStack : Stack
14+
{
15+
static StackOptions Options() => new StackOptions()
16+
{
17+
ResourceTransformations = { FailingTransform() }
18+
};
19+
20+
public MyStack() : base(Options())
21+
{
22+
var component = new Component("test", new ComponentArgs());
23+
}
24+
25+
static ResourceTransformation FailingTransform()
26+
{
27+
return args =>
28+
{
29+
throw new System.Exception("Boom!");
30+
return null;
31+
};
32+
}
33+
}
34+
35+
class Program
36+
{
37+
static Task<int> Main() => Deployment.RunAsync<MyStack>();
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
name: failing_transformation_exits
2+
description: A program that has a resource transformation which throws an exception
3+
runtime: dotnet
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net6.0</TargetFramework>
6+
</PropertyGroup>
7+
8+
</Project>

integration_tests/integration_dotnet_test.go

+13
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,19 @@ func TestLargeResourceDotNet(t *testing.T) {
301301
})
302302
}
303303

304+
// tests that when a resource transformation throws an exception, the program exits
305+
// and doesn't hang indefinitely.
306+
func TestFailingTransfomationExitsProgram(t *testing.T) {
307+
stderr := &strings.Builder{}
308+
testDotnetProgram(t, &integration.ProgramTestOptions{
309+
Dir: "failing_transformation_exits",
310+
ExpectFailure: true,
311+
Stderr: stderr,
312+
})
313+
314+
assert.Contains(t, stderr.String(), "Boom!")
315+
}
316+
304317
// Test remote component construction with a child resource that takes a long time to be created, ensuring it's created.
305318
//func TestConstructSlowDotnet(t *testing.T) {
306319
// localProvider := testComponentSlowLocalProvider(t)

sdk/Pulumi/Deployment/Deployment.EnginerLogger.cs

+1-3
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,7 @@ private Task LogImplAsync(LogSeverity severity, string message, Resource? resour
9292

9393
// Use a Task.Run here so that we don't end up aggressively running the actual
9494
// logging while holding this lock.
95-
_lastLogTask = _lastLogTask.ContinueWith(
96-
_ => Task.Run(() => LogAsync(severity, message, resource, streamId, ephemeral)),
97-
CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Default).Unwrap();
95+
_lastLogTask = Task.Run(() => LogAsync(severity, message, resource, streamId, ephemeral));
9896
task = _lastLogTask;
9997
}
10098

0 commit comments

Comments
 (0)