-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Description
The patterns we started to use while implementing #43845 are silently introducing a breaking change.
Previously, when a native socket method (eg. WSASend) returned an error within a Begin*** call, we were throwing SocketException synchronously:
runtime/src/libraries/System.Net.Sockets/src/System/Net/Sockets/Socket.cs
Lines 2492 to 2496 in f0c9552
| IAsyncResult? result = BeginSend(buffer, offset, size, socketFlags, out errorCode, callback, state); | |
| if (errorCode != SocketError.Success && errorCode != SocketError.IOPending) | |
| { | |
| throw new SocketException((int)errorCode); | |
| } |
We are no longer doing this in the methods we refactored to wrap Tasks. We are just forwarding the failed task to an IAsyncResult:
| return TaskToApm.Begin(SendAsync(new ReadOnlyMemory<byte>(buffer, offset, size), socketFlags, default).AsTask(), callback, state); |
The Task/ValueTask variants are (by design?) not throwing on sync path. This means that the APM exceptions will be only observed when invoking the corresponding
End*** calls, even if the error has been reported synchronously.
We should either switch back to old exception behavior in the APM methods, or announce this as a breaking change.
Note that this is a poorly covered functionality. The refactor work did not lead to any test failure until #47781, and even there, we only encountered it one outerloop test.
/cc @geoffkizer