Skip to content

Commit

Permalink
Fix concurrency issue with AFSelector
Browse files Browse the repository at this point in the history
Clients may iterate upon AFSelector.selectedKeys() while the selected
keys are modified in another thread.

Change the underlying datastructure to be thread-safe (use
ConcurrentHashMap), and add all "ready" selectors even if they're marked
invalid (they will be removed later).

We reimplement the fix as the original patch caused a FileDescriptor
leak and TIPC test failures.

#142
#145
  • Loading branch information
kohlschuetter committed Nov 12, 2023
1 parent 4b2bfc8 commit 889ca99
Showing 1 changed file with 5 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import java.nio.channels.spi.AbstractSelectableChannel;
import java.nio.channels.spi.AbstractSelector;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
Expand All @@ -47,8 +46,8 @@ final class AFSelector extends AbstractSelector {
private final Set<SelectionKey> keysRegisteredPublic = Collections.unmodifiableSet(
keysRegisteredKeySet);

private final Set<SelectionKey> selectedKeysSet = new HashSet<>();
private final Set<SelectionKey> selectedKeysPublic = new UngrowableSet<>(selectedKeysSet);
private final Map<SelectionKey, SelectionKey> selectedKeysSet = new ConcurrentHashMap<>();
private final Set<SelectionKey> selectedKeysPublic = new UngrowableSet<>(selectedKeysSet.keySet());

private PollFd pollFd = null;

Expand Down Expand Up @@ -185,8 +184,8 @@ private synchronized void setOpsReady(PollFd pfd) {
int rops = pfd.rops[i];
AFSelectionKey key = pfd.keys[i];
key.setOpsReady(rops);
if (rops != 0 && key.isValid()) {
selectedKeysSet.add(key);
if (rops != 0) {
selectedKeysSet.put(key, key);
}
}
}
Expand All @@ -197,7 +196,7 @@ private PollFd initPollFd(PollFd existingPollFd) throws IOException {
synchronized (this) {
for (Iterator<AFSelectionKey> it = keysRegisteredKeySet.iterator(); it.hasNext();) {
AFSelectionKey key = it.next();
if (!key.getAFCore().fd.valid() || key.hasOpInvalid()) {
if (!key.getAFCore().fd.valid() || !key.isValid()) {
key.cancelNoRemove();
it.remove();
existingPollFd = null;
Expand Down

0 comments on commit 889ca99

Please sign in to comment.