Skip to content

Commit 2920cb6

Browse files
committed
PolyglotIsolate fails to attach on some linux system with high load.
1 parent f5f839e commit 2920cb6

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;
@@ -284,18 +285,49 @@ synchronized void close() throws IOException, InterruptedException {
284285
*/
285286
ThreadChannel attachThread() throws IOException {
286287
checkState();
287-
SocketChannel c = SocketChannel.open(StandardProtocolFamily.UNIX);
288+
SocketChannel c = connectPeer();
288289
c.configureBlocking(false);
289-
boolean connected = c.connect(peer);
290-
while (!connected) {
291-
connected = c.finishConnect();
292-
}
293290
writeAttachRequest(c, ThreadInfo.current());
294291
ThreadChannel threadChannel = new ThreadChannel(this, c, null);
295292
attachedThreads.add(threadChannel);
296293
return threadChannel;
297294
}
298295

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

0 commit comments

Comments
 (0)