Skip to content

Commit 8392664

Browse files
authored
Merge pull request jruby#9305 from headius/finish_connect_in_select
Ensure connectable sockets finish
2 parents 148f885 + 41a6fb7 commit 8392664

2 files changed

Lines changed: 26 additions & 12 deletions

File tree

core/src/main/java/org/jruby/ext/socket/RubySocket.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -519,18 +519,24 @@ private boolean tryConnect(ThreadContext context, Channel channel, SocketAddress
519519

520520
while (true) {
521521
boolean result = true;
522-
if (channel instanceof SocketChannel) {
522+
if (channel instanceof UnixSocketChannel unix) {
523+
if (unix.isConnectionPending()) {
524+
// connection initiated but not finished
525+
result = unix.finishConnect();
526+
} else {
527+
result = unix.connect(addr);
528+
}
529+
} else if (channel instanceof SocketChannel) {
523530
SocketChannel socket = (SocketChannel) channel;
524531

525-
if (socket.isConnectionPending()) {
532+
if (socket.isConnected()) {
533+
return true;
534+
} else if (socket.isConnectionPending()) {
526535
// connection initiated but not finished
527536
result = socket.finishConnect();
528537
} else {
529538
result = socket.connect(addr);
530539
}
531-
} else if (channel instanceof UnixSocketChannel) {
532-
result = ((UnixSocketChannel) channel).connect((UnixSocketAddress) addr);
533-
534540
} else if (channel instanceof DatagramChannel datagram) {
535541
datagram.connect(addr);
536542
} else {

core/src/main/java/org/jruby/util/io/SelectExecutor.java

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import java.nio.channels.SelectableChannel;
1717
import java.nio.channels.SelectionKey;
1818
import java.nio.channels.Selector;
19+
import java.nio.channels.SocketChannel;
1920
import java.nio.channels.spi.SelectorProvider;
2021
import java.util.ArrayList;
2122
import 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

Comments
 (0)