Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handling of websocket connections close event #25

Open
mittster opened this issue May 1, 2023 · 0 comments
Open

Handling of websocket connections close event #25

mittster opened this issue May 1, 2023 · 0 comments

Comments

@mittster
Copy link

mittster commented May 1, 2023

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






Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant