diff --git a/junixsocket-common/src/main/java/org/newsclub/net/unix/AFSocketImpl.java b/junixsocket-common/src/main/java/org/newsclub/net/unix/AFSocketImpl.java index 51f63aec0..a99e7745e 100644 --- a/junixsocket-common/src/main/java/org/newsclub/net/unix/AFSocketImpl.java +++ b/junixsocket-common/src/main/java/org/newsclub/net/unix/AFSocketImpl.java @@ -484,7 +484,7 @@ final boolean connect0(SocketAddress addr, int connectTimeout) throws IOExceptio core.configureVirtualBlocking(true); } try { - success = NativeUnixSocket.connect(ab, ab.limit(), fd, -1); + success = NativeUnixSocket.connect(ab, ab.limit(), fd, -2); if (!success && virtualBlocking) { // try again (non-blocking timeout) if (virtualConnectTimeout == null) { @@ -627,6 +627,8 @@ public int read(byte[] buf, int off, int len) throws IOException { opt = defaultOpt; } + int read; + boolean park = false; virtualThreadLoop : do { if (virtualBlocking) { @@ -638,8 +640,17 @@ public int read(byte[] buf, int off, int len) throws IOException { } try { - return NativeUnixSocket.read(fdesc, buf, off, len, opt, ancillaryDataSupport, + read = NativeUnixSocket.read(fdesc, buf, off, len, opt, ancillaryDataSupport, socketTimeout.get()); + if (read == -2) { + if (virtualBlocking) { + // sleep again + park = true; + continue virtualThreadLoop; + } else { + read = 0; + } + } } catch (SocketTimeoutException e) { if (virtualBlocking) { // sleep again @@ -656,7 +667,10 @@ public int read(byte[] buf, int off, int len) throws IOException { core.configureVirtualBlocking(false); } } + break; // NOPMD.AvoidBranchingStatementAsLastInLoop virtualThreadLoop } while (true); // NOPMD.WhileLoopWithLiteralBoolean + + return read; } @SuppressWarnings("PMD.CognitiveComplexity") @@ -695,6 +709,15 @@ public int read() throws IOException { int byteRead = NativeUnixSocket.read(fdesc, null, 0, 1, opt, ancillaryDataSupport, socketTimeout.get()); if (byteRead < 0) { + if (byteRead == -2) { + if (virtualBlocking) { + // sleep again + park = true; + continue virtualThreadLoop; + } else { + byteRead = -1; + } + } eofReached.set(true); return -1; } else { diff --git a/junixsocket-native/src/main/c/connect.c b/junixsocket-native/src/main/c/connect.c index 91b964464..c4c413bc7 100644 --- a/junixsocket-native/src/main/c/connect.c +++ b/junixsocket-native/src/main/c/connect.c @@ -35,6 +35,14 @@ JNIEXPORT jboolean JNICALL Java_org_newsclub_net_unix_NativeUnixSocket_connect JNIEnv * env, jclass clazz CK_UNUSED, jobject ab, jint abLen, jobject fd, jlong expectedInode) { + jboolean existingConnectOK; + if(expectedInode == -2) { + expectedInode = -1; + existingConnectOK = true; + } else { + existingConnectOK = false; + } + jux_sockaddr_t *addr = (*env)->GetDirectBufferAddress(env, ab); socklen_t addrLength = (socklen_t)abLen; if(addrLength == 0) { @@ -80,7 +88,9 @@ JNIEXPORT jboolean JNICALL Java_org_newsclub_net_unix_NativeUnixSocket_connect } while(ret == -1 && myErr == EINTR); if(ret == -1) { - if(checkNonBlocking(socketHandle, myErr)) { + if(myErr == EISCONN && existingConnectOK) { + return true; + } else if(checkNonBlocking(socketHandle, myErr)) { // non-blocking connect return false; } else { diff --git a/junixsocket-native/src/main/c/receive.c b/junixsocket-native/src/main/c/receive.c index 0692c65e4..c5ff0d8c8 100644 --- a/junixsocket-native/src/main/c/receive.c +++ b/junixsocket-native/src/main/c/receive.c @@ -276,8 +276,12 @@ JNIEXPORT jint JNICALL Java_org_newsclub_net_unix_NativeUnixSocket_read( jint returnValue; if(count < 0) { // read(2) returns -1 on error. Java throws an Exception. - _throwErrnumException(env, errno, fd); - returnValue = -1; + if(errno == EWOULDBLOCK) { + returnValue = -2; + } else { + _throwErrnumException(env, errno, fd); + returnValue = -1; + } } else if(count == 0) { // read(2)/recv return 0 on EOF. Java returns -1. returnValue = -1;