90
90
import java .util .Map ;
91
91
import java .util .Set ;
92
92
import java .util .concurrent .TimeUnit ;
93
- import java .util .function .Function ;
94
93
import java .util .logging .Level ;
95
94
96
95
import org .graalvm .nativeimage .ImageInfo ;
@@ -425,9 +424,24 @@ public int[] pipeMessage() throws PosixException {
425
424
public SelectResult select (int [] readfds , int [] writefds , int [] errorfds , Timeval timeout ) throws PosixException {
426
425
SelectableChannel [] readChannels = getSelectableChannels (readfds );
427
426
SelectableChannel [] writeChannels = getSelectableChannels (writefds );
428
- SelectableChannel [] errChannels = getSelectableChannels (errorfds );
427
+ // Java doesn't support any exceptional conditions we could apply on errfds, report a
428
+ // warning if errfds is not a subset of readfds & writefds
429
+ errfdsCheck : for (int fd : errorfds ) {
430
+ for (int fd2 : readfds ) {
431
+ if (fd == fd2 ) {
432
+ continue errfdsCheck ;
433
+ }
434
+ }
435
+ for (int fd2 : writefds ) {
436
+ if (fd == fd2 ) {
437
+ continue errfdsCheck ;
438
+ }
439
+ }
440
+ compatibilityIgnored ("POSIX emultaion layer doesn't support waiting on exceptional conditions in select()" );
441
+ break ;
442
+ }
429
443
430
- boolean [] wasBlocking = new boolean [readChannels .length + writeChannels .length + errChannels . length ];
444
+ boolean [] wasBlocking = new boolean [readChannels .length + writeChannels .length ];
431
445
int i = 0 ;
432
446
433
447
for (SelectableChannel channel : readChannels ) {
@@ -436,25 +450,19 @@ public SelectResult select(int[] readfds, int[] writefds, int[] errorfds, Timeva
436
450
for (SelectableChannel channel : writeChannels ) {
437
451
wasBlocking [i ++] = channel .isBlocking ();
438
452
}
439
- for ( SelectableChannel channel : errChannels ) {
440
- wasBlocking [ i ++] = channel . isBlocking () ;
441
- }
453
+
454
+ final int readOps = SelectionKey . OP_READ | SelectionKey . OP_ACCEPT ;
455
+ final int writeOps = SelectionKey . OP_WRITE ;
442
456
443
457
try (Selector selector = Selector .open ()) {
444
458
for (SelectableChannel channel : readChannels ) {
445
459
channel .configureBlocking (false );
446
- channel .register (selector , ( SelectionKey . OP_READ | SelectionKey . OP_ACCEPT ) & channel .validOps ());
460
+ channel .register (selector , readOps & channel .validOps ());
447
461
}
448
462
449
463
for (SelectableChannel channel : writeChannels ) {
450
464
channel .configureBlocking (false );
451
- channel .register (selector , SelectionKey .OP_WRITE );
452
- }
453
-
454
- for (SelectableChannel channel : errChannels ) {
455
- // TODO(fa): not sure if these ops are representing "exceptional condition pending"
456
- channel .configureBlocking (false );
457
- channel .register (selector , SelectionKey .OP_CONNECT );
465
+ channel .register (selector , writeOps );
458
466
}
459
467
460
468
// IMPORTANT: The meaning of the timeout value is slightly different: 'timeout == 0.0'
@@ -478,9 +486,9 @@ public SelectResult select(int[] readfds, int[] writefds, int[] errorfds, Timeva
478
486
int selected = useSelectNow ? selector .selectNow () : selector .select (timeoutMs );
479
487
480
488
// remove non-selected channels from given lists
481
- boolean [] resReadfds = createSelectedMap (readfds , readChannels , selector , SelectionKey :: isReadable );
482
- boolean [] resWritefds = createSelectedMap (writefds , writeChannels , selector , SelectionKey :: isWritable );
483
- boolean [] resErrfds = createSelectedMap ( errorfds , errChannels , selector , key -> key . isAcceptable () || key . isConnectable ()) ;
489
+ boolean [] resReadfds = createSelectedMap (readfds , readChannels , selector , readOps );
490
+ boolean [] resWritefds = createSelectedMap (writefds , writeChannels , selector , writeOps );
491
+ boolean [] resErrfds = new boolean [ errorfds . length ] ;
484
492
485
493
assert selected == countSelected (resReadfds ) + countSelected (resWritefds ) + countSelected (resErrfds );
486
494
return new SelectResult (resReadfds , resWritefds , resErrfds );
@@ -499,23 +507,18 @@ public SelectResult select(int[] readfds, int[] writefds, int[] errorfds, Timeva
499
507
channel .configureBlocking (true );
500
508
}
501
509
}
502
- for (SelectableChannel channel : errChannels ) {
503
- if (wasBlocking [i ++]) {
504
- channel .configureBlocking (true );
505
- }
506
- }
507
510
} catch (IOException e ) {
508
511
// We didn't manage to restore the blocking status, ignore
509
512
}
510
513
}
511
514
}
512
515
513
- private static boolean [] createSelectedMap (int [] fds , SelectableChannel [] channels , Selector selector , Function < SelectionKey , Boolean > selectedPredicate ) {
516
+ private static boolean [] createSelectedMap (int [] fds , SelectableChannel [] channels , Selector selector , int op ) {
514
517
boolean [] result = new boolean [fds .length ];
515
518
for (int i = 0 ; i < channels .length ; i ++) {
516
519
SelectableChannel channel = channels [i ];
517
520
SelectionKey selectionKey = channel .keyFor (selector );
518
- result [i ] = selectedPredicate . apply (selectionKey ) ;
521
+ result [i ] = (selectionKey . readyOps () & op ) != 0 ;
519
522
}
520
523
return result ;
521
524
}
0 commit comments