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: Move event emitting off the main thread to avoid deadlocks #1314

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

sideshowcoder
Copy link

All code based on work by @chrfwow, based on #1299.

My current understanding is that when stacking event emitting inside an EventProvider, when using sychronization the EventProvider can deadlock, to avoid this move the event emitting of the main thread. Similar to how this is handled in EventSupport.

Still requires cleanup and moving the tests to a better location, I'm still not sure I 100% understand the reason for the deadlock, but wanted to get the work started by porting the testcase provided by @chrfwow.

@sideshowcoder sideshowcoder requested a review from a team as a code owner February 3, 2025 21:07
@sideshowcoder sideshowcoder marked this pull request as draft February 3, 2025 21:07
@sideshowcoder sideshowcoder changed the title WIP: Move event emitting off the main thread to avoid deadlocks fix: Move event emitting off the main thread to avoid deadlocks Feb 3, 2025
@sideshowcoder sideshowcoder force-pushed the sideshowcoder/issue/1299 branch 2 times, most recently from 04e35fa to 20ba91c Compare February 3, 2025 21:15
@beeme1mr beeme1mr marked this pull request as ready for review February 4, 2025 12:05
Copy link
Contributor

@chrfwow chrfwow left a comment

Choose a reason for hiding this comment

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

Looks good so far, but I have a few suggestions

toddbaert added a commit to open-feature/community that referenced this pull request Feb 4, 2025
@chrfwow has been contributing significantly to our Java implementations:

- finally hook change in SDK: open-feature/java-sdk#1246
- flag metadata support in the flagd java provider: open-feature/java-sdk-contrib#1122

And most recently identified a deadlock in the Java SDK, opened an issue describing it, and has been helping to guide the fix by a new contributor: open-feature/java-sdk#1314

I'm nominating them for Java approver. @chrfwow please approve or 👍 this PR for signal your interest.

Signed-off-by: Todd Baert <[email protected]>
@sideshowcoder sideshowcoder force-pushed the sideshowcoder/issue/1299 branch from b9f3afe to 8c36616 Compare February 4, 2025 16:25
@toddbaert
Copy link
Member

This all makes sense to me. I see 2 test failures which I'm not really surprised about. It's possible that there's actually bugs here, but more likely it's inter-test interference or test-only race conditions revealed by this change. You can try running the failing tests individually and seeing if they work as expected.

@open-feature open-feature deleted a comment from liran-p Feb 4, 2025
public abstract class EventProvider implements FeatureProvider {
private EventProviderListener eventProviderListener;
private final ExecutorService emitterExecutor = Executors.newCachedThreadPool(runnable -> {
final Thread thread = new Thread(runnable);
thread.setDaemon(true);
Copy link
Member

Choose a reason for hiding this comment

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

daemon can have it stopped before emitting the remaining events and lose data.
The shutdown() method which is later called can gracefully shut it down with a timeout.

@open-feature open-feature deleted a comment from liran-p Feb 4, 2025
@sideshowcoder sideshowcoder requested a review from chrfwow February 5, 2025 13:46
Copy link
Contributor

@chrfwow chrfwow left a comment

Choose a reason for hiding this comment

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

Your changes look good, just make sure to fix the failing tests then this PR can be merged I believe 🚀

public abstract class EventProvider implements FeatureProvider {
private EventProviderListener eventProviderListener;
private final ExecutorService emitterExecutor = Executors.newCachedThreadPool(runnable -> {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this can be simplified now that the thread is no longer modified

@sideshowcoder
Copy link
Author

sideshowcoder commented Feb 6, 2025

I am looking at the test failures locally but the seem to be passing, when run on their own, I continue to check what makes the CI run fail, I think there is some interaction going on. Just wanted to quickly update that I'm looking at this 👍

When stacking event emitting inside an EventProvider, when using sychronization
the EventProvider can deadlock, to avoid this move the event emitting of the
main thread.

Signed-off-by: Philipp Fehre <[email protected]>
@sideshowcoder sideshowcoder force-pushed the sideshowcoder/issue/1299 branch from a609ca6 to 26df9e7 Compare February 10, 2025 12:15
Test provider should respect the init-delay during all test

Signed-off-by: Philipp Fehre <[email protected]>
With the events being executed on a different thread, we need to wait to make
sure the thread is scheduled to have the events emitted.

Signed-off-by: Philipp Fehre <[email protected]>
@sideshowcoder sideshowcoder force-pushed the sideshowcoder/issue/1299 branch from 26df9e7 to 2b953e0 Compare February 10, 2025 12:45
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.

6 participants