1616import java .nio .channels .SelectableChannel ;
1717import java .nio .channels .SelectionKey ;
1818import java .nio .channels .Selector ;
19+ import java .nio .channels .SocketChannel ;
1920import java .nio .channels .spi .SelectorProvider ;
2021import java .util .ArrayList ;
2122import java .util .Collections ;
@@ -103,12 +104,11 @@ IRubyObject selectEnd(ThreadContext context) throws IOException {
103104 IRubyObject selectInternal (ThreadContext context ) throws IOException {
104105 Ruby runtime = context .runtime ;
105106 OpenFile fptr ;
106- long i ;
107107
108108 RubyArray readAry = null ;
109109 if (!read .isNil ()) {
110110 readAry = read .convertToArray ();
111- for (i = 0 ; i < readAry .size (); i ++) {
111+ for (int i = 0 ; i < readAry .size (); i ++) {
112112 fptr = TypeConverter .ioGetIO (runtime , readAry .eltOk (i )).getOpenFileChecked ();
113113 fdSetRead (context , fptr .fd (), readAry .size ());
114114 if (fptr .READ_DATA_PENDING () || fptr .READ_CHAR_PENDING ()) { /* check for buffered data */
@@ -124,7 +124,7 @@ IRubyObject selectInternal(ThreadContext context) throws IOException {
124124 RubyArray writeAry = null ;
125125 if (!write .isNil ()) {
126126 writeAry = write .convertToArray ();
127- for (i = 0 ; i < writeAry .size (); i ++) {
127+ for (int i = 0 ; i < writeAry .size (); i ++) {
128128 RubyIO write_io = TypeConverter .ioGetIO (runtime , writeAry .eltOk (i )).GetWriteIO ();
129129 fptr = write_io .getOpenFileChecked ();
130130 fdSetWrite (context , fptr .fd (), writeAry .size ());
@@ -139,7 +139,7 @@ IRubyObject selectInternal(ThreadContext context) throws IOException {
139139 // This does not actually register anything because we do not have a way to select for error on JDK.
140140 // We make the calls for their side effects.
141141 exceptAry = except .convertToArray ();
142- for (i = 0 ; i < exceptAry .size (); i ++) {
142+ for (int i = 0 ; i < exceptAry .size (); i ++) {
143143 RubyIO io = TypeConverter .ioGetIO (runtime , exceptAry .eltOk (i ));
144144 RubyIO write_io = io .GetWriteIO ();
145145 io .getOpenFileChecked ();
@@ -159,7 +159,7 @@ IRubyObject selectInternal(ThreadContext context) throws IOException {
159159 } else {
160160 final int len = Math .min (n , maxReadReadySize ());
161161 readReady = Create .allocArray (context , len );
162- for (i = 0 ; i < readAry .size (); i ++) {
162+ for (int i = 0 ; i < readAry .size (); i ++) {
163163 IRubyObject obj = readAry .eltOk (i );
164164 RubyIO io = TypeConverter .ioGetIO (runtime , obj );
165165 fptr = io .getOpenFileChecked ();
@@ -177,13 +177,21 @@ IRubyObject selectInternal(ThreadContext context) throws IOException {
177177 } else {
178178 final int len = Math .min (n , maxWriteReadySize ());
179179 writeReady = Create .allocArray (context , len );
180- for (i = 0 ; i < writeAry .size (); i ++) {
180+ for (int i = 0 ; i < writeAry .size (); i ++) {
181181 IRubyObject obj = writeAry .eltOk (i );
182182 RubyIO io = TypeConverter .ioGetIO (runtime , obj );
183183 RubyIO write_io = io .GetWriteIO ();
184184 fptr = write_io .getOpenFileChecked ();
185185 if (writeKeyList != null && fdIsSet (writeKeyList , fptr .fd (), WRITE_CONNECT_OPS ) ||
186186 (unselectableWriteFDs != null && unselectableWriteFDs .contains (fptr .fd ()))) {
187+
188+ // ensure any pending connections get finished
189+ if (writeKeyList != null && writeKeyList .get (i ).isConnectable ()) {
190+ if (fptr .fd ().ch instanceof SocketChannel sock ) {
191+ sock .finishConnect ();
192+ }
193+ }
194+
187195 writeReady .push (context , obj );
188196 }
189197 }
@@ -194,7 +202,7 @@ IRubyObject selectInternal(ThreadContext context) throws IOException {
194202 error = newEmptyArray (context );
195203 } else {
196204 error = Create .allocArray (context , exceptAry .size ());
197- for (i = 0 ; i < exceptAry .size (); i ++) {
205+ for (int i = 0 ; i < exceptAry .size (); i ++) {
198206 IRubyObject obj = exceptAry .eltOk (i );
199207 RubyIO io = TypeConverter .ioGetIO (runtime , obj );
200208 RubyIO write_io = io .GetWriteIO ();
0 commit comments