mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 03:58:21 +00:00
8370655: Check EINTR handling InetAddress implementation and NET_ThrowNew
Reviewed-by: alanb
This commit is contained in:
parent
9e2008bf5e
commit
4924b29fa5
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user