Problems persist in KQueueSelectorProvider (Mac) in 7u6 ea
Jason T. Greene
jason.greene at redhat.com
Mon Aug 13 12:13:49 PDT 2012
On 8/13/12 3:11 AM, Alan Bateman wrote:
-snip-
> I see Jason's reply on setInterest and there is indeed a problem there.
> The specification is that changing the interest set is effective at the
> next select operation but this Selector is doing it asynchronously. This
> needs to be changed to batch the changes to the next select as is done
> in the other Selector implementations. I will create a bug for that.
Ah that should have been obvious to me! Thanks for that.
I threw together a quick patch (attached below against 7u-dev), and it
appears to resolve the issues on 6 and 7. Although it needs more testing.
The preClose problem disappears as well with this change. My hunch is
that the tight spin loop on kqueue makes it impossible for close/dup2 to
ever complete.
--
Jason T. Greene
JBoss AS Lead / EAP Platform Architect
JBoss, a division of Red Hat
-------------- next part --------------
diff -r 043839897cd9 src/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java
--- a/src/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java Thu Aug 09 20:46:39 2012 -0700
+++ b/src/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java Mon Aug 13 14:04:08 2012 -0500
@@ -34,7 +34,8 @@
import sun.misc.*;
import java.io.IOException;
import java.io.FileDescriptor;
-
+import java.util.Iterator;
+import java.util.LinkedList;
/*
* struct kevent { // 32-bit 64-bit
@@ -99,6 +100,18 @@
kq = init();
}
+ // Used to update file description registrations
+ private static class Update {
+ SelChImpl channel;
+ int events;
+ Update(SelChImpl channel, int events) {
+ this.channel = channel;
+ this.events = events;
+ }
+ }
+
+ private LinkedList<Update> updateList = new LinkedList<Update>();
+
void initInterrupt(int fd0, int fd1) {
outgoingInterruptFD = fd1;
incomingInterruptFD = fd0;
@@ -136,14 +149,41 @@
}
}
- void setInterest(int fd, int events) {
- register0(kq, fd, events & POLLIN, events & POLLOUT);
+ void setInterest(SelChImpl channel, int events) {
+ synchronized (updateList) {
+ // update existing registration
+ updateList.add(new Update(channel, events));
+ }
}
- void release(int fd) {
- register0(kq, fd, 0, 0);
+ void release(SelChImpl channel) {
+ synchronized (updateList) {
+ // flush any pending updates
+ for (Iterator<Update> it = updateList.iterator(); it.hasNext();) {
+ if (it.next().channel == channel) {
+ it.remove();
+ }
+ }
+
+ // remove
+ register0(kq, channel.getFDVal(), 0, 0);
+ }
}
+ void updateRegistrations() {
+ synchronized (updateList) {
+ Update u = null;
+ while ((u = updateList.poll()) != null) {
+ SelChImpl ch = u.channel;
+ if (!ch.isOpen())
+ continue;
+
+ register0(kq, ch.getFDVal(), u.events & POLLIN, u.events & POLLOUT);
+ }
+ }
+ }
+
+
void close() throws IOException {
if (keventArray != null) {
keventArray.free();
@@ -156,6 +196,7 @@
}
int poll(long timeout) {
+ updateRegistrations();
int updated = kevent0(kq, keventArrayAddress, NUM_KEVENTS, timeout);
return updated;
}
diff -r 043839897cd9 src/macosx/classes/sun/nio/ch/KQueueSelectorImpl.java
--- a/src/macosx/classes/sun/nio/ch/KQueueSelectorImpl.java Thu Aug 09 20:46:39 2012 -0700
+++ b/src/macosx/classes/sun/nio/ch/KQueueSelectorImpl.java Mon Aug 13 14:04:08 2012 -0500
@@ -86,7 +86,7 @@
fd1 = (int)fds;
kqueueWrapper = new KQueueArrayWrapper();
kqueueWrapper.initInterrupt(fd0, fd1);
- fdMap = new HashMap<>();
+ fdMap = new HashMap<Integer,MapEntry>();
totalChannels = 1;
}
@@ -184,7 +184,6 @@
FileDispatcherImpl.closeIntFD(fd0);
FileDispatcherImpl.closeIntFD(fd1);
if (kqueueWrapper != null) {
- kqueueWrapper.release(fd0);
kqueueWrapper.close();
kqueueWrapper = null;
selectedKeys = null;
@@ -220,7 +219,7 @@
protected void implDereg(SelectionKeyImpl ski) throws IOException {
int fd = ski.channel.getFDVal();
fdMap.remove(Integer.valueOf(fd));
- kqueueWrapper.release(fd);
+ kqueueWrapper.release(ski.channel);
totalChannels--;
keys.remove(ski);
selectedKeys.remove(ski);
@@ -234,8 +233,7 @@
public void putEventOps(SelectionKeyImpl ski, int ops) {
if (closed)
throw new ClosedSelectorException();
- int fd = IOUtil.fdVal(ski.channel.getFD());
- kqueueWrapper.setInterest(fd, ops);
+ kqueueWrapper.setInterest(ski.channel, ops);
}
More information about the nio-dev
mailing list