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

Protect caches from being modified concurrently #746

Merged
merged 3 commits into from
Feb 20, 2024

Conversation

seadowg
Copy link
Member

@seadowg seadowg commented Feb 15, 2024

Fixes this crash.

The only way I can see the crash occurring is if two evaluations for the same thing happen at once. In that case, we could end up modifying the index for the same key concurrently, creating the scenario which could cause a crash (an null returned for a key we just checked).

My solution here is to synchronize accesses to the index (and doing the same thing for our comparison cache for good measure) to prevent them happening concurrently.

What has been done to verify that this works as intended?

It's really hard to test this stuff without injecting some kind of executor into the objects and this can often result in pretty contrived examples. The best I can do here is to reason about the possible concurrent accesses.

Why is this the best possible solution? Were any other approaches considered?

An alternative to using synchronized here would be to use a lock in the FilterStrategy that can be conditionally acquired. If the lock can't be acquired, we could actually just fall through to the next strategy hoping that that is thread safe (or not currently locked by another thread at least). We'd probably want both EqualityExpressionIndexFilterStrategy and ComparisonExpressionCacheFilterStrategy to behave like this. I'm assuming that RawFilterStrategy is thread safe. I think I like that more than the PR solution (and it's also far easier to test), but the PR solution is far simpler and swifter fix for the crash as far as I can tell.

Falling through on a failed lock attempt would be a good follow up.

How does this change affect users? Describe intentional changes to behavior and behavior that could have accidentally been affected by code changes. In other words, what are the regression risks?

The risk here is a performance drop if a thread ends up waiting for a lock. This is especially bad news in Collect if the thread waiting for the lock is the UI/main one. It's hard to say whether that scenario is better or worse than the thread actually taking the time to evaluate the filter however.

@seadowg seadowg modified the milestones: v4.3.0, v4.3.x Feb 15, 2024
@seadowg seadowg marked this pull request as ready for review February 15, 2024 14:00
@lognaturel lognaturel merged commit a340649 into getodk:master Feb 20, 2024
3 checks passed
@seadowg seadowg deleted the synchronized branch February 21, 2024 09:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: done
Development

Successfully merging this pull request may close these issues.

None yet

2 participants