Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 1e0eabe

Browse files
stephentoubAnipik
authored andcommitted
Fix CancellationTokenRegistration.Unregister race condition (#27949)
1 parent 0402229 commit 1e0eabe

File tree

1 file changed

+9
-1
lines changed

1 file changed

+9
-1
lines changed

src/System.Private.CoreLib/shared/System/Threading/CancellationTokenSource.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,7 @@ internal CancellationTokenRegistration InternalRegister(
524524
{
525525
// Assign the next available unique ID.
526526
id = partition.NextAvailableId++;
527+
Debug.Assert(id != 0, "IDs should never be the reserved value 0.");
527528

528529
// Get a node, from the free list if possible or else a new one.
529530
node = partition.FreeNodeList;
@@ -942,9 +943,16 @@ public CallbackPartition(CancellationTokenSource source)
942943

943944
internal bool Unregister(long id, CallbackNode node)
944945
{
945-
Debug.Assert(id != 0, "Expected non-zero id");
946946
Debug.Assert(node != null, "Expected non-null node");
947947

948+
if (id == 0)
949+
{
950+
// In general, we won't get 0 passed in here. However, race conditions between threads
951+
// Unregistering and also zero'ing out the CancellationTokenRegistration could cause 0
952+
// to be passed in here, in which case there's nothing to do. 0 is never a valid id.
953+
return false;
954+
}
955+
948956
bool lockTaken = false;
949957
Lock.Enter(ref lockTaken);
950958
try

0 commit comments

Comments
 (0)