diff --git a/src/java.base/share/native/libnet/net_util.c b/src/java.base/share/native/libnet/net_util.c index 5b356d04b3c75..7b148f03cfde7 100644 --- a/src/java.base/share/native/libnet/net_util.c +++ b/src/java.base/share/native/libnet/net_util.c @@ -86,7 +86,6 @@ DEF_JNI_OnLoad(JavaVM *vm, void *reserved) /* check if SO_REUSEPORT is supported on this platform */ REUSEPORT_available = reuseport_supported(IPv6_available); - return JNI_VERSION_1_2; } diff --git a/src/java.base/unix/native/libnet/Inet4AddressImpl.c b/src/java.base/unix/native/libnet/Inet4AddressImpl.c index fff524e03ae97..f537226c330ba 100644 --- a/src/java.base/unix/native/libnet/Inet4AddressImpl.c +++ b/src/java.base/unix/native/libnet/Inet4AddressImpl.c @@ -108,7 +108,8 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, hints.ai_flags = AI_CANONNAME; hints.ai_family = AF_INET; - error = getaddrinfo(hostname, NULL, &hints, &res); + NET_RESTARTABLE(error, getaddrinfo(hostname, NULL, &hints, &res), + error == EAI_SYSTEM && errno == EINTR); if (error) { #if defined(MACOSX) @@ -229,17 +230,21 @@ Java_java_net_Inet4AddressImpl_getHostByAddr(JNIEnv *env, jobject this, sa.sin_addr.s_addr = htonl(addr); sa.sin_family = AF_INET; - if (getnameinfo((struct sockaddr *)&sa, sizeof(struct sockaddr_in), - host, sizeof(host), NULL, 0, NI_NAMEREQD)) { - JNU_ThrowByName(env, "java/net/UnknownHostException", NULL); - } else { + int r; + + NET_RESTARTABLE(r, getnameinfo((struct sockaddr *)&sa, sizeof(struct sockaddr_in), + host, sizeof(host), NULL, 0, NI_NAMEREQD), + r == EAI_SYSTEM && errno == EINTR); + + if (r == 0) { ret = (*env)->NewStringUTF(env, host); - if (ret == NULL) { - JNU_ThrowByName(env, "java/net/UnknownHostException", NULL); + if (ret != NULL) { + return ret; } } - return ret; + JNU_ThrowByName(env, "java/net/UnknownHostException", NULL); + return NULL; } /** @@ -283,7 +288,8 @@ tcp_ping4(JNIEnv *env, SOCKETADDRESS *sa, SOCKETADDRESS *netif, jint timeout, SET_NONBLOCKING(fd); sa->sa4.sin_port = htons(7); // echo port - connect_rv = connect(fd, &sa->sa, sizeof(struct sockaddr_in)); + NET_RESTARTABLE(connect_rv, connect(fd, &sa->sa, sizeof(struct sockaddr_in)), + connect_rv == -1 && errno == EINTR); // connection established or refused immediately, either way it means // we were able to reach the host! @@ -397,8 +403,11 @@ ping4(JNIEnv *env, jint fd, SOCKETADDRESS *sa, SOCKETADDRESS *netif, icmp->icmp_cksum = 0; // manually calculate checksum icmp->icmp_cksum = in_cksum((u_short *)icmp, plen); + // send it - n = sendto(fd, sendbuf, plen, 0, &sa->sa, sizeof(struct sockaddr_in)); + NET_RESTARTABLE(n, sendto(fd, sendbuf, plen, 0, &sa->sa, sizeof(struct sockaddr_in)), + n == -1 && errno == EINTR) + if (n < 0 && errno != EINPROGRESS) { #if defined(__linux__) /* @@ -422,8 +431,9 @@ ping4(JNIEnv *env, jint fd, SOCKETADDRESS *sa, SOCKETADDRESS *netif, tmout2 = NET_Wait(env, fd, NET_WAIT_READ, tmout2); if (tmout2 >= 0) { len = sizeof(sa_recv); - n = recvfrom(fd, recvbuf, sizeof(recvbuf), 0, - (struct sockaddr *)&sa_recv, &len); + NET_RESTARTABLE(n, recvfrom(fd, recvbuf, sizeof(recvbuf), 0, + (struct sockaddr *)&sa_recv, &len), + n == -1 && errno == EINTR); // check if we received enough data if (n < (jint)sizeof(struct ip)) { continue; diff --git a/src/java.base/unix/native/libnet/Inet6AddressImpl.c b/src/java.base/unix/native/libnet/Inet6AddressImpl.c index 83354356936db..8dce4f9cc6bd8 100644 --- a/src/java.base/unix/native/libnet/Inet6AddressImpl.c +++ b/src/java.base/unix/native/libnet/Inet6AddressImpl.c @@ -227,7 +227,8 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, hints.ai_flags = AI_CANONNAME; hints.ai_family = lookupCharacteristicsToAddressFamily(characteristics); - error = getaddrinfo(hostname, NULL, &hints, &res); + NET_RESTARTABLE(error, getaddrinfo(hostname, NULL, &hints, &res), + error == EAI_SYSTEM && errno == EINTR); if (error) { #if defined(MACOSX) @@ -430,16 +431,20 @@ Java_java_net_Inet6AddressImpl_getHostByAddr(JNIEnv *env, jobject this, len = sizeof(struct sockaddr_in6); } - if (getnameinfo(&sa.sa, len, host, sizeof(host), NULL, 0, NI_NAMEREQD)) { - JNU_ThrowByName(env, "java/net/UnknownHostException", NULL); - } else { + int r; + + NET_RESTARTABLE(r, getnameinfo(&sa.sa, len, host, sizeof(host), NULL, 0, NI_NAMEREQD), + r == EAI_SYSTEM && errno == EINTR); + + if (r == 0) { ret = (*env)->NewStringUTF(env, host); - if (ret == NULL) { - JNU_ThrowByName(env, "java/net/UnknownHostException", NULL); + if (ret != NULL) { + return ret; } } - return ret; + JNU_ThrowByName(env, "java/net/UnknownHostException", NULL); + return NULL; } /** @@ -483,7 +488,8 @@ tcp_ping6(JNIEnv *env, SOCKETADDRESS *sa, SOCKETADDRESS *netif, jint timeout, SET_NONBLOCKING(fd); sa->sa6.sin6_port = htons(7); // echo port - connect_rv = connect(fd, &sa->sa, sizeof(struct sockaddr_in6)); + NET_RESTARTABLE(connect_rv, connect(fd, &sa->sa, sizeof(struct sockaddr_in6)), + connect_rv == -1 && errno == EINTR); // connection established or refused immediately, either way it means // we were able to reach the host! @@ -604,7 +610,10 @@ ping6(JNIEnv *env, jint fd, SOCKETADDRESS *sa, SOCKETADDRESS *netif, memcpy(sendbuf + sizeof(struct icmp6_hdr), &tv, sizeof(tv)); icmp6->icmp6_cksum = 0; // send it - n = sendto(fd, sendbuf, plen, 0, &sa->sa, sizeof(struct sockaddr_in6)); + + NET_RESTARTABLE(n, sendto(fd, sendbuf, plen, 0, &sa->sa, sizeof(struct sockaddr_in6)), + n == -1 && errno == EINTR); + if (n < 0 && errno != EINPROGRESS) { #if defined(__linux__) /* @@ -628,8 +637,9 @@ ping6(JNIEnv *env, jint fd, SOCKETADDRESS *sa, SOCKETADDRESS *netif, tmout2 = NET_Wait(env, fd, NET_WAIT_READ, tmout2); if (tmout2 >= 0) { len = sizeof(sa_recv); - n = recvfrom(fd, recvbuf, sizeof(recvbuf), 0, - (struct sockaddr *)&sa_recv, &len); + NET_RESTARTABLE(n, recvfrom(fd, recvbuf, sizeof(recvbuf), 0, + (struct sockaddr *)&sa_recv, &len), + n == -1 && errno == EINTR); // check if we received enough data if (n < (jint)sizeof(struct icmp6_hdr)) { continue; diff --git a/src/java.base/unix/native/libnet/net_util_md.c b/src/java.base/unix/native/libnet/net_util_md.c index 9bb6a02696151..b0915615d9658 100644 --- a/src/java.base/unix/native/libnet/net_util_md.c +++ b/src/java.base/unix/native/libnet/net_util_md.c @@ -76,9 +76,6 @@ NET_ThrowNew(JNIEnv *env, int errorNumber, char *msg) { jio_snprintf(fullMsg, sizeof(fullMsg), "socket closed: %s", msg); JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", fullMsg); break; - case EINTR: - JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", msg); - break; default: errno = errorNumber; JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", msg); @@ -627,11 +624,11 @@ NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout) pfd.fd = fd; pfd.events = 0; if (flags & NET_WAIT_READ) - pfd.events |= POLLIN; + pfd.events |= POLLIN; if (flags & NET_WAIT_WRITE) - pfd.events |= POLLOUT; + pfd.events |= POLLOUT; if (flags & NET_WAIT_CONNECT) - pfd.events |= POLLOUT; + pfd.events |= POLLOUT; errno = 0; read_rv = poll(&pfd, 1, nanoTimeout / NET_NSEC_PER_MSEC); @@ -639,13 +636,13 @@ NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout) newNanoTime = JVM_NanoTime(env, 0); nanoTimeout -= (newNanoTime - prevNanoTime); if (nanoTimeout < NET_NSEC_PER_MSEC) { - return read_rv > 0 ? 0 : -1; + return read_rv > 0 ? 0 : -1; } prevNanoTime = newNanoTime; if (read_rv > 0) { - break; + break; } - } /* while */ + } /* while */ return (nanoTimeout / NET_NSEC_PER_MSEC); } diff --git a/src/java.base/unix/native/libnet/net_util_md.h b/src/java.base/unix/native/libnet/net_util_md.h index 902cf96732fe4..d6cb3250bbe09 100644 --- a/src/java.base/unix/native/libnet/net_util_md.h +++ b/src/java.base/unix/native/libnet/net_util_md.h @@ -80,4 +80,17 @@ void NET_ThrowUnknownHostExceptionWithGaiError(JNIEnv *env, void NET_ThrowByNameWithLastError(JNIEnv *env, const char *name, const char *defaultDetail); +/** + * Invokes CALL in a loop, setting RET to return value. + * Invokes PREDICATE for condition to restart CALL (in loop) + * Return RET otherwise + */ +#define NET_RESTARTABLE(RET,CALL,PREDICATE) \ + while (1) { \ + RET = CALL; \ + if (!(PREDICATE)) { \ + break; \ + } \ + } + #endif /* NET_UTILS_MD_H */