Skip to content

Commit 56cb488

Browse files
committed
[GR-66721] PolyglotIsolate fails to attach on some linux system with high load.
PullRequest: graal/21285
2 parents d05be0f + 2920cb6 commit 56cb488

File tree

1 file changed

+37
-5
lines changed

1 file changed

+37
-5
lines changed

sdk/src/org.graalvm.nativebridge/src/org/graalvm/nativebridge/ProcessIsolateThreadSupport.java

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import java.net.StandardProtocolFamily;
4848
import java.net.UnixDomainSocketAddress;
4949
import java.nio.ByteBuffer;
50+
import java.nio.channels.ClosedByInterruptException;
5051
import java.nio.channels.SelectionKey;
5152
import java.nio.channels.Selector;
5253
import java.nio.channels.ServerSocketChannel;
@@ -285,18 +286,49 @@ synchronized void close() throws IOException, InterruptedException {
285286
*/
286287
ThreadChannel attachThread() throws IOException {
287288
checkState();
288-
SocketChannel c = SocketChannel.open(StandardProtocolFamily.UNIX);
289+
SocketChannel c = connectPeer();
289290
c.configureBlocking(false);
290-
boolean connected = c.connect(peer);
291-
while (!connected) {
292-
connected = c.finishConnect();
293-
}
294291
writeAttachRequest(c, ThreadInfo.current());
295292
ThreadChannel threadChannel = new ThreadChannel(this, c, null);
296293
attachedThreads.add(threadChannel);
297294
return threadChannel;
298295
}
299296

297+
/**
298+
* Connects to the peer process using blocking socket channel.
299+
*
300+
* <p>
301+
* Using a non-blocking {@link SocketChannel} for the initial connect can fail on some Linux
302+
* systems under high load, throwing a {@link java.net.SocketException} with
303+
* {@code errno = EAGAIN (Resource temporarily unavailable)}. This makes non-blocking connect
304+
* unreliable in such environments.
305+
*
306+
* <p>
307+
* Although {@link Selector} and {@link SelectionKey#OP_CONNECT} can be used to wait for the
308+
* completion of a connection, they cannot be used to initiate it. Therefore, this method
309+
* performs the connect in blocking mode.
310+
*
311+
* <p>
312+
* If the connect attempt is interrupted (e.g., due to {@link Thread#interrupt()}), the
313+
* resulting {@link ClosedByInterruptException} is caught and ignored, and the method retries.
314+
* This avoids propagating the exception, which is important for distinguishing between
315+
* cancellation and interruption in {@code IsolateDeathHandler} as both {@code Context.close()}
316+
* and {@code Context.interrupt()} interrupt threads.
317+
*/
318+
private SocketChannel connectPeer() throws IOException {
319+
while (true) {
320+
SocketChannel c = SocketChannel.open(StandardProtocolFamily.UNIX);
321+
try {
322+
c.connect(peer);
323+
return c;
324+
} catch (ClosedByInterruptException closed) {
325+
// Retry on interrupt to avoid leaking cancellation semantics into
326+
// IsolateDeathHandler.
327+
// Closing or interrupting contexts may interrupt this thread.
328+
}
329+
}
330+
}
331+
300332
/**
301333
* Retrieves the local address of the {@code AF_UNIX} socket used by this instance.
302334
*

0 commit comments

Comments
 (0)