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

fix race condition for FirstLimiter #1101

Merged
merged 1 commit into from
Jan 2, 2024

Conversation

tinnou
Copy link
Contributor

@tinnou tinnou commented Dec 18, 2023

Description

Under contention the CardinalityLimiters.FirstLimiter will stop accepting values before its limit has been reached.
This behavior happens when more than one thread add the same value to the limiter value registry and the remaining property is decremented even though no new entry has been added.

Steps to reproduce

I added a test in CardinalityLimitersConcurrencyTest that reproduces the issue fairly consistently. It simulates threads submitting the same series of numbers and expect all numbers to be registered. A failing test example output is below, note the --others-- entries that should not be present.

at least one number was not registered in the limiter, 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,--others--,--others--,--others--,--others--,--others--

Fix proposal

After acquiring the lock, we can check if the limiter value registry contains the key before inserting the entry and decrementing remaining.

@@ -193,7 +193,7 @@ private void add(String s) {
// Lock to keep hashmap consistent with counter for remaining
lock.lock();
try {
if (remaining.get() > 0) {
if (remaining.get() > 0 && !values.containsKey(s)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This can just check if values.put(s, s) == null. That way it avoids a second operation on the map in the case it is successful.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ah good point, will update.

@brharrington brharrington added this to the 1.7.5 milestone Dec 18, 2023
Updates the logic to only decrement the remaining counter
if an entry was successfully added.
@brharrington brharrington merged commit 0e3090d into Netflix:main Jan 2, 2024
1 check passed
@brharrington brharrington changed the title FirstLimiter race fix race condition for FirstLimiter Jan 4, 2024
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

Successfully merging this pull request may close these issues.

2 participants