Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ private async Task ProcessSocketAsync(WebSocket socket)

if (trigger == receiving)
{
// Observe exception if there is one to avoid unobserved tasks
_ = receiving.Exception;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't these exceptions matter? Should we at least be logging them?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably should, but to no higher than Debug since they will include client disconnects.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Debug ftw

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should never actually have exceptions in them, I was just being paranoid. We have a try catch around both sending and receiving so the only exceptions that could escape would be Pipe.Complete throwing, logger throwing, or socket.CloseOutputAsync (this would be the one most likely to throw).

I'll just wrap socket.CloseOutputAsync and log it if it throws.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we get rid of all the _ = blah.Exception lines then?

The mere existence of these lines communicates to other developers that these tasks could have completed with an exception. I don't want to risk seeing this pattern copied more widely. The more places this pattern is used, the more likely it will be copied somewhere else.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'm good with removing them

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool. If for whatever reason we are still concerned about something unexpected throwing, we could also replace the _ = blah.Exception with await trigger. That way if there was an unexpected error, WebSocketTransport.StopAsync() would rethrow it.


// We're waiting for the application to finish and there are 2 things it could be doing
// 1. Waiting for application data
// 2. Waiting for a websocket send to complete
Expand All @@ -176,13 +179,19 @@ private async Task ProcessSocketAsync(WebSocket socket)
}
else
{
// Observe exception if there is one to avoid unobserved tasks
_ = sending.Exception;

// Cancel the timeout
delayCts.Cancel();
}
}
}
else
{
// Observe exception if there is one to avoid unobserved tasks
_ = sending.Exception;

// We're waiting on the websocket to close and there are 2 things it could be doing
// 1. Waiting for websocket data
// 2. Waiting on a flush to complete (backpressure being applied)
Expand Down Expand Up @@ -269,10 +278,6 @@ private async Task StartReceiving(WebSocket socket)
if (!_aborted)
{
_application.Output.Complete(ex);

// We re-throw here so we can communicate that there was an error when sending
// the close frame
throw;

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the main culprit for unobserved tasks.

An alternative solution would be to keep this and actually observe the exception and set a private field to let the send loop know to send an internal server error instead of possibly a normal exit code.
https://github.com/aspnet/AspNetCore/blob/010ffe612150d9a3f5b78f2ad3ffcee3aedef369/src/SignalR/common/Http.Connections/src/Internal/Transports/WebSocketsTransport.cs#L272

}
}
finally
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ public async Task ProcessSocketAsync(WebSocket socket)

if (trigger == receiving)
{
// Observe exception if there is one to avoid unobserved tasks
_ = receiving.Exception;

Log.WaitingForSend(_logger);

// We're waiting for the application to finish and there are 2 things it could be doing
Expand All @@ -102,12 +105,18 @@ public async Task ProcessSocketAsync(WebSocket socket)
}
else
{
// Observe exception if there is one to avoid unobserved tasks
_ = sending.Exception;

delayCts.Cancel();
}
}
}
else
{
// Observe exception if there is one to avoid unobserved tasks
_ = sending.Exception;

Log.WaitingForClose(_logger);

// We're waiting on the websocket to close and there are 2 things it could be doing
Expand All @@ -130,6 +139,9 @@ public async Task ProcessSocketAsync(WebSocket socket)
}
else
{
// Observe exception if there is one to avoid unobserved tasks
_ = receiving.Exception;

delayCts.Cancel();
}
}
Expand Down Expand Up @@ -189,10 +201,6 @@ private async Task StartReceiving(WebSocket socket)
if (!_aborted && !token.IsCancellationRequested)
{
_application.Output.Complete(ex);

// We re-throw here so we can communicate that there was an error when sending
// the close frame
throw;
}
}
finally
Expand Down