WebSocket4Net icon indicating copy to clipboard operation
WebSocket4Net copied to clipboard

Unhandled "cannot access a disposed object" exception

Open LolliDepp opened this issue 7 years ago • 6 comments

This seems to have happened seconds after the client handled a disconnect from the server. The client had been running for about 2 hours already

I didn't delve in the source just yet but it looks like this may be solved just by checking if the timer is disposed

Here are the logs:

Cannot access a disposed object. at System.Threading.TimerQueueTimer.Change(UInt32 dueTime, UInt32 period) at WebSocket4Net.WebSocket.ClearTimer() at WebSocket4Net.WebSocket.FireClosed() at WebSocket4Net.WebSocket.OnClosed() at SuperSocket.ClientEngine.ClientSession.OnClosed() at SuperSocket.ClientEngine.AsyncTcpSession.ProcessReceive(SocketAsyncEventArgs e) at System.Net.Sockets.SocketAsyncEventArgs.OnCompleted(SocketAsyncEventArgs e) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Net.Sockets.SocketAsyncEventArgs.FinishOperationSuccess(SocketError socketError, Int32 bytesTransferred, SocketFlags flags) at System.Net.Sockets.SocketAsyncEventArgs.CompletionPortCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped) at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)

LolliDepp avatar Nov 07 '18 10:11 LolliDepp

Faced similar issue. Though I see a fix already applied for handling a disposed timer here - a4bcac3, using v0.15.2

aady501 avatar Nov 27 '19 09:11 aady501

Catched same exception in v0.15.2.11

Polimat avatar Jan 16 '20 11:01 Polimat

me to System.ObjectDisposedException: Cannot access a disposed object. at System.Threading.TimerQueueTimer.Change(UInt32 dueTime, UInt32 period) at System.Threading.Timer.Change(Int32 dueTime, Int32 period) at WebSocket4Net.WebSocket.ClearTimer() at WebSocket4Net.WebSocket.FireClosed() at WebSocket4Net.WebSocket.OnClosed() at SuperSocket.ClientEngine.AuthenticatedStreamTcpSession.SendInternal(PosList`1 items) at System.Net.LazyAsyncResult.Complete(IntPtr userToken) at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken) at System.Net.Security._SslStream.StartWriting(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security._SslStream.WriteCallback(IAsyncResult transportResult) at System.Net.LazyAsyncResult.Complete(IntPtr userToken) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Net.ContextAwareResult.Complete(IntPtr userToken) at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken) at System.Net.Sockets.BaseOverlappedAsyncResult.CompletionPortCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped) at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)

NektoDron avatar Mar 10 '20 08:03 NektoDron

Can also confirm. Interlocked.CompareExchange was changed to lock statement at 1ab610a. I think this change is not equivalent. In my case, this bug happens when both client and server close connection. I suppose that two threads may enter that lock section: my code and data receiving thread. When my code calls Close first, then ping timer is replaced by closing handshake timer. But at the same time receiving thread may also call ClearTimer, so both will simultaneously enter lock. Receiving thread code will check m_WebSocketTimer that will not be null, then dispose old local timer copy that have already been disposed by my code.

aubiyko avatar Jun 16 '20 12:06 aubiyko

Same error here as well

Cannot access a disposed object. at System.Threading.TimerQueueTimer.Change(UInt32 dueTime, UInt32 period) at System.Threading.Timer.Change(Int32 dueTime, Int32 period) at WebSocket4Net.WebSocket.ClearTimer() at WebSocket4Net.WebSocket.FireClosed() at WebSocket4Net.WebSocket.OnClosed() at SuperSocket.ClientEngine.AuthenticatedStreamTcpSession.OnDataRead(IAsyncResult result) at System.Net.LazyAsyncResult.Complete(IntPtr userToken) at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken) at System.Net.AsyncProtocolRequest.CompleteWithError(Exception e) at System.Net.Security._SslStream.ReadHeaderCallback(AsyncProtocolRequest asyncRequest) at System.Net.AsyncProtocolRequest.CompleteRequest(Int32 result) at System.Net.FixedSizeReader.CheckCompletionBeforeNextRead(Int32 bytes) at System.Net.FixedSizeReader.ReadCallback(IAsyncResult transportResult) at System.Net.LazyAsyncResult.Complete(IntPtr userToken) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Net.ContextAwareResult.Complete(IntPtr userToken) at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken) at System.Net.Sockets.BaseOverlappedAsyncResult.CompletionPortCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped) at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)

MarkoPielic avatar May 15 '23 08:05 MarkoPielic

We are hitting this routinely during stress tests.

Could it be caused by the double-checked locking on a non-volatile field used inside ClearTimer() here: https://github.com/kerryjiang/WebSocket4Net/blob/v0.15/WebSocket4Net/WebSocket.cs#L710

julbra avatar Jul 05 '23 12:07 julbra