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

Prevent concurrent use corruption from causing infinite loops #16991

Merged
merged 2 commits into from
Mar 17, 2018

Conversation

benaadams
Copy link
Member

Copy link
Member

@jkotas jkotas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@@ -2539,6 +2539,9 @@
<data name="InvalidOperation_CollectionCorrupted" xml:space="preserve">
<value>A prior operation on this collection was interrupted by an exception. Collection's state is no longer trusted.</value>
</data>
<data name="InvalidOperation_ConcurrentOperationsNotSupported" xml:space="preserve">
<value>Concurrent operations are not supported on non-concurrent collections. A concurrent operation was performed on this collection and corrupted its state. Collection's state is no longer correct.</value>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: "Collection's state" => "The collection's state"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Concurrent reads are supported right? Maybe "Operations that change this collection must have exclusive access" or something like that?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now says:

Operations that change non-concurrent collections must have exclusive access. A concurrent update was performed on this collection and corrupted its state. The collection's state is no longer correct.

How's that?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds fine.

// The chain of entires forms a loop; which means a concurrent update has happened.
// Break out of the loop and throw; rather than looping forever.
ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported();
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What kind of measurable impact, if any, does this have on TryGetValue?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It shouldn't impact items that haven't collided (as they don't loop); hoping it will be minimal; but will have a look.

On the flip side, what's the alternative?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the flip side, what's the alternative?

If it's very negatively impactful, not doing it.

@@ -382,6 +383,13 @@ private int FindEntry(TKey key)
}

i = entries[i].next;
if (loops >= entries.Length)
{
// The chain of entires forms a loop; which means a concurrent update has happened.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: search and replace "entires" => "entries"

if (loops >= entries.Length)
{
// The chain of entires forms a loop; which means a concurrent update has happened.
// Break out of the loop and throw; rather than looping forever.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: ';' => ',' (same in the other copies of this)

// Break out of the loop and throw; rather than looping forever.
ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported();
}
loops++;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about using the same name collisioncount throughout?

Copy link
Member

@safern safern left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc: @ianhays

Copy link
Member

@danmoseley danmoseley left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @benaadams !

@jkotas jkotas merged commit f2f327d into dotnet:master Mar 17, 2018
@benaadams benaadams deleted the concurrent-dict branch March 17, 2018 01:28
@vancem
Copy link

vancem commented Mar 19, 2018

Note that the original idea from Feng was on HashSet not Dictionary<K, V>. I think it was reasonable that this issue is more likely on Dictionary since it is used more commonly. Still it may be worth determining whether we apply this change to HashSet.

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

Successfully merging this pull request may close these issues.

7 participants