Skip to content

Fix concurrency issue from modifying the selectedKeysSet#141

Merged
kohlschuetter merged 1 commit intokohlschutter:mainfrom
kevink-sq:fix-jetty-concurrency-issue
Oct 27, 2023
Merged

Fix concurrency issue from modifying the selectedKeysSet#141
kohlschuetter merged 1 commit intokohlschutter:mainfrom
kevink-sq:fix-jetty-concurrency-issue

Conversation

@kevink-sq
Copy link
Copy Markdown
Contributor

@kevink-sq kevink-sq commented Oct 25, 2023

This bug may have been a regression introduced in optimizing the key removal: a7c3106

To reproduce refer to poc: https://github.com/kevink-sq/jetty-concurrency-issue-poc

To verify fix, refer to poc branch (same as these changes): https://github.com/kevink-sq/jetty-concurrency-issue-poc/tree/kevink/attempted-junixsocket-fix-2

Jetty's ManagedSelector iterates through the selectedKeysSet and when separate processes cancel the AFSelectorKey, the iterator throws a ConcurrentModificationException.

Fix is to introduce cancelledKeysSet to defer removal of cancelled keys until the select process. Use of the cancelled sets are referenced from java.nio.channels.spi's AbstractSelector and AbstractSelectionKey.

Other socket implementation such as jnr-unixsocket extends the abstract classes (ref). Native Java sockets synchronize on the selectedSet (ref)

Ideally we'd have AFSelectionKey extend from AbstractSelectionKey to leverage the base class's internal cancelled set but AbstractSelectionKey defines its own isValid and cancel and cannot override the base's final methods.

Also added an atomic check to AFSelectionKey#cancel to prevent "Too many open files" socket exception.

cc: @ThePumpingLemma who did most of the rca

This bug may have been a regression introduced in optimizing the key removal: kohlschutter@a7c3106

To reproduce refer to poc:
https://github.com/kevink-sq/jetty-concurrency-issue-poc

To verify fix, refer to poc branch (same as these changes):
https://github.com/kevink-sq/jetty-concurrency-issue-poc/tree/kevink/attempted-junixsocket-fix-2

Jetty's [ManagedSelector](https://github.com/jetty/jetty.project/blob/7a7d69a69f4f51772e20813332291189a24e91b1/jetty-io/src/main/java/org/eclipse/jetty/io/ManagedSelector.java#L655)
iterates through the selectedKeysSet and when separate processes cancel
the AFSelectorKey, the iterator throws a `ConcurrentModificationException`.

Fix is to introduce `cancelledKeysSet` to defer removal of cancelled
keys until the select process. Use of the cancelled sets are referenced
from java.nio.channels.spi's `AbstractSelector` and `AbstractSelectionKey`.

Ideally we'd have `AFSelectionKey` extend from `AbstractSelectionKey` to
leverage the base class's internal cancelled set
but`AbstractSelectionKey` defines its own `isValid` and `cancel` and
cannot override the base's final methods.

Also added an atomic check to  `AFSelectionKey#cancel` to prevent "Too
many open files" socket exception.
@kohlschuetter kohlschuetter merged commit b8386a1 into kohlschutter:main Oct 27, 2023
@kohlschuetter
Copy link
Copy Markdown
Member

Thanks for the fix! 👍

@kohlschuetter
Copy link
Copy Markdown
Member

I just noticed that somehow this change breaks a test in junixsocket-tipc. Investigating...

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