CitadelCore.Windows icon indicating copy to clipboard operation
CitadelCore.Windows copied to clipboard

Handling of websocket connections close event

Open mittster opened this issue 3 years ago • 0 comments

On websocket termination (triggered by browser tab closure), a number of catch blocks catch an exception. The relevant code and stack trace is appended. I normally just ignore these errors and I haven't noticed any problems because the thing you are doing is already done after the connection is closed. So apart from cluttering the error logs, they appear to be benign. But I wonder.. Do they cause any side effects and should they be prevented? The code is from FilterWebsocketHandler.cs and FilterHttpResponseHandler.cs .The below stack is generated by tab close event. Thank you.

//FilterWebsocketHandler.cs
0+249 // Spawn an async task that will poll the remote server for data in a loop, and then
1+249                // write any data it gets to the client websocket.
2+249                var serverTask = Task.Run(async () =>
3+249                {
4+249                    System.Net.WebSockets.WebSocketReceiveResult serverResult = null;
5+249                    var serverBuffer = new byte[1024 * 4];
6+249                    try
7+249                    {
8+249                        bool looping = true;
9+249
10+249                        serverResult = await wsServer.ReceiveAsync(new ArraySegment<byte>(serverBuffer), context.RequestAborted);
11+249
12+249                        while (looping && !serverResult.CloseStatus.HasValue && !context.RequestAborted.IsCancellationRequested)
13+249                        {
14+249
15+249                            if (inspect)
16+249                            {
17+249                                serverMessageInfo.Body = new Memory<byte>(serverBuffer, 0, serverResult.Count);
18+249
19+249                                switch (serverResult.MessageType)
20+249                                {
21+249                                    case System.Net.WebSockets.WebSocketMessageType.Binary:
22+249                                        {
23+249                                            serverMessageInfo.BodyContentType = s_octetStreamContentType;
24+249                                        }
25+249                                        break;
26+249
27+249                                    case System.Net.WebSockets.WebSocketMessageType.Text:
28+249                                        {
29+249                                            serverMessageInfo.BodyContentType = s_plainTextContentType;
30+249                                        }
31+249                                        break;
32+249                                }
33+249
34+249                                _configuration.HttpMessageWholeBodyInspectionHandler?.Invoke(serverMessageInfo, null);
35+249                            }
36+249
37+249                            switch (serverMessageInfo.ProxyNextAction)
38+249                            {
39+249                                case ProxyNextAction.DropConnection:
40+249                                    {
41+249                                        looping = false;
42+249                                    }
43+249                                    break;
44+249
45+249                                default:
46+249                                    {
47+249                                        await wsClient.SendAsync(new ArraySegment<byte>(serverBuffer, 0, serverResult.Count), serverResult.MessageType, serverResult.EndOfMessage, context.RequestAborted);
48+249
49+249                                        if (!wsClient.CloseStatus.HasValue)
50+249                                        {
51+249                                            serverResult = await wsServer.ReceiveAsync(new ArraySegment<byte>(serverBuffer), context.RequestAborted); // this triggers an exception #0
52+249                                            continue;
53+249                                        }
54+249                                    }
55+249                                    break;
56+249                            }
57+249
58+249                            looping = false;
59+249                        }
60+249
61+249                        await wsClient.CloseAsync(serverResult.CloseStatus.Value, serverResult.CloseStatusDescription, context.RequestAborted);// this triggers an exception #1
62+249                    }
63+249                    catch (Exception e)
64+249                    {
65+249                        LoggerProxy.Default.Error(e.ToString());
66+249                        try{
67+249                            var closeStatus = serverResult?.CloseStatus ??
68+249                                              System.Net.WebSockets.WebSocketCloseStatus.NormalClosure;
69+249                            var closeMessage = serverResult?.CloseStatusDescription ?? string.Empty;
70+249
71+249                            await wsClient.CloseAsync(closeStatus, closeMessage, context.RequestAborted);// this triggers an exception #2
72+249                        }
73+249                        catch (Exception e2){
74+249                            LoggerProxy.Default.Error(e2.ToString());
75+249
76+249                        }
77+249                    }
78+249                });
79+249
80+249                // Spawn an async task that will poll the local client websocket, in a loop, and then
81+249                // write any data it gets to the remote server websocket.
82+249                var clientTask = Task.Run(async () =>
83+249                {
84+249                    System.Net.WebSockets.WebSocketReceiveResult clientResult = null;
85+249                    var clientBuffer = new byte[1024 * 4];
86+249                    try
87+249                    {
88+249                        bool looping = true;
89+249
90+249                        clientResult = await wsClient.ReceiveAsync(new ArraySegment<byte>(clientBuffer), context.RequestAborted);
91+249
92+249                        while (looping && !clientResult.CloseStatus.HasValue && !context.RequestAborted.IsCancellationRequested)
93+249                        {
94+249                            if (inspect)
95+249                            {
96+249                                clientMessageInfo.Body = new Memory<byte>(clientBuffer, 0, clientResult.Count);
97+249
98+249                                switch (clientResult.MessageType)
99+249                                {
100+249                                    case System.Net.WebSockets.WebSocketMessageType.Binary:
101+249                                        {
102+249                                            clientMessageInfo.BodyContentType = s_octetStreamContentType;
103+249                                        }
104+249                                        break;
105+249
106+249                                    case System.Net.WebSockets.WebSocketMessageType.Text:
107+249                                        {
108+249                                            clientMessageInfo.BodyContentType = s_plainTextContentType;
109+249                                        }
110+249                                        break;
111+249                                }
112+249
113+249                                _configuration.HttpMessageWholeBodyInspectionHandler?.Invoke(clientMessageInfo, null);
114+249                            }
115+249
116+249                            switch (clientMessageInfo.ProxyNextAction)
117+249                            {
118+249                                case ProxyNextAction.DropConnection:
119+249                                    {
120+249                                        looping = false;
121+249                                    }
122+249                                    break;
123+249
124+249                                default:
125+249                                    {
126+249                                        await wsServer.SendAsync(new ArraySegment<byte>(clientBuffer, 0, clientResult.Count), clientResult.MessageType, clientResult.EndOfMessage, context.RequestAborted);
127+249
128+249                                        if (!wsServer.CloseStatus.HasValue)
129+249                                        {
130+249                                            clientResult = await wsClient.ReceiveAsync(new ArraySegment<byte>(clientBuffer), context.RequestAborted);
131+249                                            continue;
132+249                                        }
133+249                                    }
134+249                                    break;
135+249                            }
136+249
137+249                            looping = false;
138+249                        }
139+249
140+249                        await wsServer.CloseAsync(clientResult.CloseStatus.Value, clientResult.CloseStatusDescription, context.RequestAborted);// this triggers an exception #3
141+249                    }
142+249                    catch(Exception e)
143+249                    {
144+249
145+249                        LoggerProxy.Default.Error(e.ToString());
146+249                        try{
147+249                            var closeStatus = clientResult?.CloseStatus ??
148+249                                              System.Net.WebSockets.WebSocketCloseStatus.NormalClosure;
149+249                            var closeMessage = clientResult?.CloseStatusDescription ?? string.Empty;
150+249
151+249                            await wsServer.CloseAsync(closeStatus, closeMessage, context.RequestAborted);// this triggers an exception #4
152+249                        }
153+249                        catch (Exception e2){
154+249                            LoggerProxy.Default.Error(e2.ToString());
155+249                        }
156+249                    }
157+249                });
158+249
159+249                // Above, we have created a bridge between the local and remote websocket. Wait for
160+249                // both associated tasks to complete.
161+249                await Task.WhenAll(serverTask, clientTask);
//  FilterHttpResponseHandler.cs
0+386                   try
1+386                    {
2+386                        if (false){
3+386                            
4+386                        }
5+386                        response = await upstreamClient.SendAsync(requestMsg, HttpCompletionOption.ResponseHeadersRead, context.RequestAborted);
6+386                    }
7+386                    catch (Exception e)
8+386                    {

Exceptions:

ERRO: System.OperationCanceledException: Aborted ---> System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'SslStream'.
   at System.Net.Security.SslState.CheckThrow(Boolean authSuccessCheck, Boolean shutdownCheck)
   at System.Net.Security.SslState.get_SecureStream()
   at System.Net.Security.SslStream.EndRead(IAsyncResult asyncResult)
   at System.IO.Stream.<>c.<BeginEndReadAsync>b__43_1(Stream stream, IAsyncResult asyncResult)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncTrimPromise`1.Complete(TInstance thisRef, Func`3 endMethod, IAsyncResult asyncResult, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Relay.Websockets.Managed.ManagedWebSocket.<EnsureBufferContainsAsync>d__70.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult()
   at Relay.Websockets.Managed.ManagedWebSocket.<ReceiveAsyncPrivate>d__61.MoveNext()
   --- End of inner exception stack trace ---
   at Relay.Websockets.Managed.ManagedWebSocket.<ReceiveAsyncPrivate>d__61.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at Relay.Net.Handlers.FilterWebsocketHandler.<>c__DisplayClass4_1.<<Handle>b__0>d.MoveNext() in C:\Users\pathtoproject\Net\Handlers\FilterWebsocketHandler.cs:line 300

ERRO: System.Threading.Tasks.TaskCanceledException: A task was canceled.
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Net.Http.HttpClient.<FinishSendAsyncUnbuffered>d__59.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at Relay.Net.Handlers.FilterHttpResponseHandler.<Handle>d__7.MoveNext() in C:\Users\pathtoproject\Net\Handlers\FilterHttpResponseHandler.cs:line 391
ERRO: System.OperationCanceledException: Aborted ---> System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'SslStream'.
   at System.Net.Security.SslState.CheckThrow(Boolean authSuccessCheck, Boolean shutdownCheck)
   at System.Net.Security.SslState.get_SecureStream()
   at System.Net.Security.SslStream.EndRead(IAsyncResult asyncResult)
   at System.IO.Stream.<>c.<BeginEndReadAsync>b__43_1(Stream stream, IAsyncResult asyncResult)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncTrimPromise`1.Complete(TInstance thisRef, Func`3 endMethod, IAsyncResult asyncResult, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Relay.Websockets.Managed.ManagedWebSocket.<EnsureBufferContainsAsync>d__70.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult()
   at Relay.Websockets.Managed.ManagedWebSocket.<ReceiveAsyncPrivate>d__61.MoveNext()
   --- End of inner exception stack trace ---
   at Relay.Websockets.Managed.ManagedWebSocket.<ReceiveAsyncPrivate>d__61.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at Relay.Net.Handlers.FilterWebsocketHandler.<>c__DisplayClass4_1.<<Handle>b__0>d.MoveNext() in C:\Users\pathtoproject\Net\Handlers\FilterWebsocketHandler.cs:line 0
ERRO: System.Threading.Tasks.TaskCanceledException: A task was canceled.
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.WebSockets.Protocol.CommonWebSocket.<CloseOutputAsync>d__42.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.WebSockets.Protocol.CommonWebSocket.<CloseAsync>d__41.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Relay.Net.Handlers.FilterWebsocketHandler.<>c__DisplayClass4_1.<<Handle>b__0>d.MoveNext() in C:\Users\pathtoproject\Net\Handlers\FilterWebsocketHandler.cs:line 320


ERRO: System.OperationCanceledException: Aborted ---> System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'SslStream'.
   at System.Net.Security.SslState.CheckThrow(Boolean authSuccessCheck, Boolean shutdownCheck)
   at System.Net.Security.SslState.get_SecureStream()
   at System.Net.Security.SslStream.EndRead(IAsyncResult asyncResult)
   at System.IO.Stream.<>c.<BeginEndReadAsync>b__43_1(Stream stream, IAsyncResult asyncResult)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncTrimPromise`1.Complete(TInstance thisRef, Func`3 endMethod, IAsyncResult asyncResult, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Relay.Websockets.Managed.ManagedWebSocket.<EnsureBufferContainsAsync>d__70.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult()
   at Relay.Websockets.Managed.ManagedWebSocket.<ReceiveAsyncPrivate>d__61.MoveNext()
   --- End of inner exception stack trace ---
   at Relay.Websockets.Managed.ManagedWebSocket.<ReceiveAsyncPrivate>d__61.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
   at Relay.Websockets.Managed.ManagedWebSocket.<CloseAsyncPrivate>d__67.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Relay.Net.Handlers.FilterWebsocketHandler.<>c__DisplayClass4_1.<<Handle>b__1>d.MoveNext() in C:\Users\pathtoproject\Net\Handlers\FilterWebsocketHandler.cs:line 389


ERRO: System.TypeInitializationException: The type initializer for 'System.SR' threw an exception. ---> System.Resources.MissingManifestResourceException: Could not find any resources appropriate for the specified culture or the neutral culture.  Make sure
"Relay.Websockets.Client.Managed.Strings.resources" was correctly embedded or linked into assembly "ProjectSockets" at compile time, or that all the satellite assemblies required are loadable and fully signed.
   at System.Resources.ManifestBasedResourceGroveler.HandleResourceStreamMissing(String fileName)
   at System.Resources.ManifestBasedResourceGroveler.GrovelForResourceSet(CultureInfo culture, Dictionary`2 localResourceSets, Boolean tryParents, Boolean createIfNotExists, StackCrawlMark& stackMark)
   at System.Resources.ResourceManager.InternalGetResourceSet(CultureInfo requestedCulture, Boolean createIfNotExists, Boolean tryParents, StackCrawlMark& stackMark)
   at System.Resources.ResourceManager.InternalGetResourceSet(CultureInfo culture, Boolean createIfNotExists, Boolean tryParents)
   at System.Resources.ResourceManager.GetString(String name, CultureInfo culture)
   at Relay.Websockets.Client.Managed.Strings.get_net_WebSockets_InvalidCloseStatusDescription()
   at System.SR..cctor()
   --- End of inner exception stack trace ---
   at Relay.Websockets.Managed.WebSocketValidate.ThrowIfInvalidState(WebSocketState currentState, Boolean isDisposed, WebSocketState[] validStates)
   at Relay.Websockets.Managed.ManagedWebSocket.CloseAsync(WebSocketCloseStatus closeStatus, String statusDescription, CancellationToken cancellationToken)
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Relay.Net.Handlers.FilterWebsocketHandler.<>c__DisplayClass4_1.<<Handle>b__1>d.MoveNext() in C:\Users\pathtoproject\Net\Handlers\FilterWebsocketHandler.cs:line 400






mittster avatar May 01 '23 09:05 mittster