8370655: Check EINTR handling InetAddress implementation and NET_ThrowNew

Reviewed-by: alanb
This commit is contained in:
Michael McMahon 2025-12-17 08:54:56 +00:00
parent 9e2008bf5e
commit 4924b29fa5
5 changed files with 62 additions and 33 deletions

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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);
}

View File

@ -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 */