Skip to content

Commit 33daff7

Browse files
committed
nonblocking waitSelect code doesnt need to be in RubyThread.BlockingTask, and catch more successful selects in case there is more than one selected key due to a JRuby bug
1 parent 8ddf4e8 commit 33daff7

File tree

1 file changed

+47
-43
lines changed

1 file changed

+47
-43
lines changed

src/main/java/org/jruby/ext/openssl/SSLSocket.java

Lines changed: 47 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -384,49 +384,53 @@ private Object waitSelect(final int operations, final boolean blocking, final bo
384384
final SelectionKey key = channel.register(selector, operations);
385385

386386
try {
387-
io.addBlockingThread(thread);
388-
389387
final int[] result = new int[1];
390388

391-
thread.executeBlockingTask(new RubyThread.BlockingTask() {
392-
public void run() throws InterruptedException {
393-
try {
394-
if ( ! blocking ) {
395-
result[0] = selector.selectNow();
396-
397-
if ( result[0] == 0 ) {
398-
if ((operations & SelectionKey.OP_READ) != 0 && (operations & SelectionKey.OP_WRITE) != 0) {
399-
if ( key.isReadable() ) {
400-
writeWouldBlock(runtime, exception, result); return;
401-
}
402-
//else if ( key.isWritable() ) {
403-
// readWouldBlock(runtime, exception, result);
404-
//}
405-
else { //neither, pick one
406-
readWouldBlock(runtime, exception, result); return;
407-
}
408-
}
409-
else if ((operations & SelectionKey.OP_READ) != 0) {
410-
readWouldBlock(runtime, exception, result); return;
411-
}
412-
else if ((operations & SelectionKey.OP_WRITE) != 0) {
413-
writeWouldBlock(runtime, exception, result); return;
414-
}
389+
if ( ! blocking ) {
390+
try {
391+
result[0] = selector.selectNow();
392+
393+
if ( result[0] == 0 ) {
394+
if ((operations & SelectionKey.OP_READ) != 0 && (operations & SelectionKey.OP_WRITE) != 0) {
395+
if ( key.isReadable() ) {
396+
writeWouldBlock(runtime, exception, result);
415397
}
398+
//else if ( key.isWritable() ) {
399+
// readWouldBlock(runtime, exception, result);
400+
//}
401+
else { //neither, pick one
402+
readWouldBlock(runtime, exception, result);
403+
}
404+
}
405+
else if ((operations & SelectionKey.OP_READ) != 0) {
406+
readWouldBlock(runtime, exception, result);
416407
}
417-
else {
408+
else if ((operations & SelectionKey.OP_WRITE) != 0) {
409+
writeWouldBlock(runtime, exception, result);
410+
}
411+
}
412+
}
413+
catch (IOException ioe) {
414+
throw runtime.newRuntimeError("Error with selector: " + ioe.getMessage());
415+
}
416+
} else {
417+
io.addBlockingThread(thread);
418+
thread.executeBlockingTask(new RubyThread.BlockingTask() {
419+
public void run() throws InterruptedException {
420+
try {
418421
result[0] = selector.select();
419422
}
423+
catch (IOException ioe) {
424+
throw runtime.newRuntimeError("Error with selector: " + ioe.getMessage());
425+
}
420426
}
421-
catch (IOException ioe) {
422-
throw runtime.newRuntimeError("Error with selector: " + ioe.getMessage());
427+
428+
public void wakeup() {
429+
selector.wakeup();
423430
}
424-
}
431+
});
432+
}
425433

426-
public void wakeup() {
427-
selector.wakeup();
428-
}
429-
});
430434

431435
switch ( result[0] ) {
432436
case READ_WOULD_BLOCK_RESULT :
@@ -435,11 +439,9 @@ public void wakeup() {
435439
return runtime.newSymbol("wait_writable"); // exception: false
436440
case 0 : return Boolean.FALSE;
437441
default :
438-
if ( result[0] >= 1 ) {
439-
Set<SelectionKey> keySet = selector.selectedKeys();
440-
if ( keySet.iterator().next() == key ) return Boolean.TRUE;
441-
}
442-
return Boolean.FALSE;
442+
//key should always be contained in selectedKeys() here, however there is a bug in
443+
//JRuby <= 9.1.2.0 that makes this not always the case, so we have to check
444+
return selector.selectedKeys().contains(key) ? Boolean.TRUE : Boolean.FALSE;
443445
}
444446
}
445447
catch (InterruptedException interrupt) { return Boolean.FALSE; }
@@ -469,11 +471,13 @@ public void wakeup() {
469471
debugStackTrace(runtime, e);
470472
}
471473

472-
// remove this thread as a blocker against the given IO
473-
io.removeBlockingThread(thread);
474+
if (blocking) {
475+
// remove this thread as a blocker against the given IO
476+
io.removeBlockingThread(thread);
474477

475-
// clear thread state from blocking call
476-
thread.afterBlockingCall();
478+
// clear thread state from blocking call
479+
thread.afterBlockingCall();
480+
}
477481
}
478482
}
479483

0 commit comments

Comments
 (0)