Skip to content

Race condition in PooledSocket.DisposeSocket() can throw NullReferenceException from cancellation callback and crash process #271

@XiLiuRoy

Description

@XiLiuRoy

Summary

Race condition in PooledSocket.DisposeSocket() can throw NullReferenceException from cancellation callback and crash process

System.NullReferenceException: Object reference not set to an instance of an object.
at Enyim.Caching.Memcached.PooledSocket.DisposeSocket()
at System.Threading.CancellationTokenSource.Invoke(Delegate d, Object state, CancellationTokenSource source)

Suspected root cause

In PooledSocket.Connect():

a timeout CTS is created (CancelAfter(...))
callback calls DisposeSocket() when _socket != null && !_socket.Connected
DisposeSocket() currently does:

_isSocketDisposed = true;
_socket.Dispose();
_socket = null;
This is not thread-safe/idempotent.
The callback’s check-then-act on _socket can race with other cleanup paths (Destroy / Dispose(true) / another callback), so _socket may become null between check and _socket.Dispose(), causing NullReferenceException.

The exception is thrown from CancellationTokenSource callback execution path (Invoke/ExecuteCallbackHandlers) and can surface as unhandled process-level failure.

Repro notes

PooledSocket.Connect() (short connection timeout / unreachable endpoint)
concurrent disposal (Destroy())
This repeatedly triggers callback/dispose interleavings and can crash test host with stack frames in PooledSocket.DisposeSocket + CTS callback handlers.

Code Snippet and potential fix

private void DisposeSocket()
{
// Only the thread that transitions 0->1 proceeds; all others return immediately.
if (Interlocked.Exchange(ref _disposeState, 1) != 0)
return;
var socket = Interlocked.Exchange(ref _socket, null);
socket?.Dispose();
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions