Skip to content

Commit aa1ccfd

Browse files
committed
Ignoring fatal exceptions in InvocationHandler
1 parent 7b1bd29 commit aa1ccfd

File tree

4 files changed

+66
-8
lines changed

4 files changed

+66
-8
lines changed

sdk/release_notes.md

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,10 @@
44
- My change description (#PR/#issue)
55
-->
66

7-
### Microsoft.Azure.Functions.Worker.Sdk 1.18.1
7+
### Microsoft.Azure.Functions.Worker.Sdk <version>
88

9-
- Updated `Microsoft.Azure.Functions.Worker.Sdk.Generators` reference to 1.3.4.
9+
- Changed exception handling in function invocation path to ensure fatal exceptions bubble up.
1010

11-
### Microsoft.Azure.Functions.Worker.Sdk.Generators 1.3.4
12-
13-
- Changed `FunctionExecutorGenerator` to avoid generation of long `if`/`else` chains for apps with a large number of functions.
14-
15-
- Use full namespace for `Task.FromResult` in function metadata provider generator to avoid namespace conflict (#2681)
11+
### Microsoft.Azure.Functions.Worker.Sdk.Generators <version>
1612

1713
- <entry>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System;
2+
3+
namespace Microsoft.Azure.Functions.Worker.Core
4+
{
5+
internal static class ExceptionExtensions
6+
{
7+
public static bool IsFatal(this Exception? exception)
8+
{
9+
while (exception is not null)
10+
{
11+
if (exception
12+
is (OutOfMemoryException and not InsufficientMemoryException)
13+
or AppDomainUnloadedException
14+
or BadImageFormatException
15+
or CannotUnloadAppDomainException
16+
or InvalidProgramException
17+
or AccessViolationException)
18+
{
19+
return true;
20+
}
21+
22+
exception = exception.InnerException;
23+
}
24+
25+
return false;
26+
}
27+
}
28+
}

src/DotNetWorker.Grpc/Handlers/InvocationHandler.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Threading;
77
using System.Threading.Tasks;
88
using Microsoft.Azure.Functions.Worker.Context.Features;
9+
using Microsoft.Azure.Functions.Worker.Core;
910
using Microsoft.Azure.Functions.Worker.Grpc;
1011
using Microsoft.Azure.Functions.Worker.Grpc.Features;
1112
using Microsoft.Azure.Functions.Worker.Grpc.Messages;
@@ -113,7 +114,7 @@ public async Task<InvocationResponse> InvokeAsync(InvocationRequest request)
113114

114115
response.Result.Status = StatusResult.Types.Status.Success;
115116
}
116-
catch (Exception ex)
117+
catch (Exception ex) when (!ex.IsFatal())
117118
{
118119
response.Result.Exception = _workerOptions.EnableUserCodeException ? ex.ToUserRpcException() : ex.ToRpcException();
119120
response.Result.Status = StatusResult.Types.Status.Failure;
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using System;
2+
using Microsoft.Azure.Functions.Worker.Core;
3+
using Xunit;
4+
5+
namespace Microsoft.Azure.Functions.Worker.Tests
6+
{
7+
public class ExceptionExtensionTests
8+
{
9+
[Theory]
10+
[ClassData(typeof(ExceptionTestData))]
11+
public void IsFatal_ReturnsTrueForFatalExceptions(Exception exception, bool isFatal)
12+
{
13+
var result = exception.IsFatal();
14+
15+
Assert.Equal(result, isFatal);
16+
}
17+
18+
public class ExceptionTestData : TheoryData<Exception, bool>
19+
{
20+
public ExceptionTestData()
21+
{
22+
Add(new OutOfMemoryException(), true);
23+
Add(new AppDomainUnloadedException(), true);
24+
Add(new BadImageFormatException(), true);
25+
Add(new CannotUnloadAppDomainException(), true);
26+
Add(new InvalidProgramException(), true);
27+
Add(new AccessViolationException(), true);
28+
Add(new InsufficientMemoryException(), false);
29+
Add(new Exception("test", new OutOfMemoryException()), true);
30+
}
31+
}
32+
}
33+
}

0 commit comments

Comments
 (0)