mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-06 14:10:36 +00:00
8075484: SocketInputStream.socketRead0 can hang even with soTimeout set
Reviewed-by: chegar, dsamersoff, msheppar, clanger
This commit is contained in:
parent
a2daf82f5c
commit
912fe7e358
@ -410,6 +410,10 @@ int NET_Read(int s, void* buf, size_t len) {
|
||||
BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) );
|
||||
}
|
||||
|
||||
int NET_NonBlockingRead(int s, void* buf, size_t len) {
|
||||
BLOCKING_IO_RETURN_INT(s, recv(s, buf, len, MSG_NONBLOCK));
|
||||
}
|
||||
|
||||
int NET_ReadV(int s, const struct iovec * vector, int count) {
|
||||
BLOCKING_IO_RETURN_INT( s, readv(s, vector, count) );
|
||||
}
|
||||
@ -503,8 +507,8 @@ int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
|
||||
* Auto restarts with adjusted timeout if interrupted by
|
||||
* signal other than our wakeup signal.
|
||||
*/
|
||||
int NET_Timeout(int s, long timeout) {
|
||||
long prevtime = 0, newtime;
|
||||
int NET_Timeout0(int s, long timeout, long currentTime) {
|
||||
long prevtime = currentTime, newtime;
|
||||
struct timeval t;
|
||||
fdEntry_t *fdEntry = getFdEntry(s);
|
||||
|
||||
@ -516,14 +520,6 @@ int NET_Timeout(int s, long timeout) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pick up current time as may need to adjust timeout
|
||||
*/
|
||||
if (timeout > 0) {
|
||||
gettimeofday(&t, NULL);
|
||||
prevtime = t.tv_sec * 1000 + t.tv_usec / 1000;
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
struct pollfd pfd;
|
||||
int rv;
|
||||
|
||||
@ -367,6 +367,10 @@ int NET_Read(int s, void* buf, size_t len) {
|
||||
BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) );
|
||||
}
|
||||
|
||||
int NET_NonBlockingRead(int s, void* buf, size_t len) {
|
||||
BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, MSG_DONTWAIT) );
|
||||
}
|
||||
|
||||
int NET_ReadV(int s, const struct iovec * vector, int count) {
|
||||
BLOCKING_IO_RETURN_INT( s, readv(s, vector, count) );
|
||||
}
|
||||
@ -406,8 +410,8 @@ int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
|
||||
* Auto restarts with adjusted timeout if interrupted by
|
||||
* signal other than our wakeup signal.
|
||||
*/
|
||||
int NET_Timeout(int s, long timeout) {
|
||||
long prevtime = 0, newtime;
|
||||
int NET_Timeout0(int s, long timeout, long currentTime) {
|
||||
long prevtime = currentTime, newtime;
|
||||
struct timeval t;
|
||||
fdEntry_t *fdEntry = getFdEntry(s);
|
||||
|
||||
@ -419,14 +423,6 @@ int NET_Timeout(int s, long timeout) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pick up current time as may need to adjust timeout
|
||||
*/
|
||||
if (timeout > 0) {
|
||||
gettimeofday(&t, NULL);
|
||||
prevtime = t.tv_sec * 1000 + t.tv_usec / 1000;
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
struct pollfd pfd;
|
||||
int rv;
|
||||
|
||||
@ -371,6 +371,10 @@ int NET_Read(int s, void* buf, size_t len) {
|
||||
BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) );
|
||||
}
|
||||
|
||||
int NET_NonBlockingRead(int s, void* buf, size_t len) {
|
||||
BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, MSG_DONTWAIT));
|
||||
}
|
||||
|
||||
int NET_ReadV(int s, const struct iovec * vector, int count) {
|
||||
BLOCKING_IO_RETURN_INT( s, readv(s, vector, count) );
|
||||
}
|
||||
@ -410,8 +414,8 @@ int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
|
||||
* Auto restarts with adjusted timeout if interrupted by
|
||||
* signal other than our wakeup signal.
|
||||
*/
|
||||
int NET_Timeout(int s, long timeout) {
|
||||
long prevtime = 0, newtime;
|
||||
int NET_Timeout0(int s, long timeout, long currentTime) {
|
||||
long prevtime = currentTime, newtime;
|
||||
struct timeval t, *tp = &t;
|
||||
fd_set fds;
|
||||
fd_set* fdsp = NULL;
|
||||
@ -432,9 +436,6 @@ int NET_Timeout(int s, long timeout) {
|
||||
*/
|
||||
if (timeout > 0) {
|
||||
/* Timed */
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
prevtime = now.tv_sec * 1000 + now.tv_usec / 1000;
|
||||
t.tv_sec = timeout / 1000;
|
||||
t.tv_usec = (timeout % 1000) * 1000;
|
||||
} else if (timeout < 0) {
|
||||
|
||||
@ -35,7 +35,7 @@
|
||||
if (1) { \
|
||||
do { \
|
||||
_result = _cmd; \
|
||||
} while((_result == -1) && (errno == EINTR)); \
|
||||
} while((_result == -1) && (errno == EINTR)); \
|
||||
return _result; \
|
||||
} \
|
||||
} while(0)
|
||||
@ -44,6 +44,10 @@ int NET_Read(int s, void* buf, size_t len) {
|
||||
RESTARTABLE_RETURN_INT(recv(s, buf, len, 0));
|
||||
}
|
||||
|
||||
int NET_NonBlockingRead(int s, void* buf, size_t len) {
|
||||
RESTARTABLE_RETURN_INT(recv(s, buf, len, MSG_DONTWAIT));
|
||||
}
|
||||
|
||||
int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
|
||||
struct sockaddr *from, socklen_t *fromlen) {
|
||||
RESTARTABLE_RETURN_INT(recvfrom(s, buf, len, flags, from, fromlen));
|
||||
@ -86,19 +90,14 @@ int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout) {
|
||||
RESTARTABLE_RETURN_INT(poll(ufds, nfds, timeout));
|
||||
}
|
||||
|
||||
int NET_Timeout(int s, long timeout) {
|
||||
int NET_Timeout0(int s, long timeout, long currentTime) {
|
||||
int result;
|
||||
struct timeval t;
|
||||
long prevtime, newtime;
|
||||
long prevtime = currentTime, newtime;
|
||||
struct pollfd pfd;
|
||||
pfd.fd = s;
|
||||
pfd.events = POLLIN;
|
||||
|
||||
if (timeout > 0) {
|
||||
gettimeofday(&t, NULL);
|
||||
prevtime = (t.tv_sec * 1000) + t.tv_usec / 1000;
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
result = poll(&pfd, 1, timeout);
|
||||
if (result < 0 && errno == EINTR) {
|
||||
|
||||
@ -35,7 +35,6 @@
|
||||
|
||||
#include "java_net_SocketInputStream.h"
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* SocketInputStream
|
||||
*/
|
||||
@ -52,6 +51,40 @@ Java_java_net_SocketInputStream_init(JNIEnv *env, jclass cls) {
|
||||
IO_fd_fdID = NET_GetFileDescriptorID(env);
|
||||
}
|
||||
|
||||
static int NET_ReadWithTimeout(JNIEnv *env, int fd, char *bufP, int len, long timeout) {
|
||||
int result = 0;
|
||||
long prevtime = NET_GetCurrentTime(), newtime;
|
||||
while (timeout > 0) {
|
||||
result = NET_TimeoutWithCurrentTime(fd, timeout, prevtime);
|
||||
if (result <= 0) {
|
||||
if (result == 0) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException", "Read timed out");
|
||||
} else if (result == -1) {
|
||||
if (errno == EBADF) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
|
||||
} else if (errno == ENOMEM) {
|
||||
JNU_ThrowOutOfMemoryError(env, "NET_Timeout native heap allocation failed");
|
||||
} else {
|
||||
JNU_ThrowByNameWithMessageAndLastError
|
||||
(env, JNU_JAVANETPKG "SocketException", "select/poll failed");
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
result = NET_NonBlockingRead(fd, bufP, len);
|
||||
if (result == -1 && ((errno == EAGAIN) || (errno == EWOULDBLOCK))) {
|
||||
newtime = NET_GetCurrentTime();
|
||||
timeout -= newtime - prevtime;
|
||||
if (timeout > 0) {
|
||||
prevtime = newtime;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: java_net_SocketInputStream
|
||||
* Method: socketRead0
|
||||
@ -98,32 +131,18 @@ Java_java_net_SocketInputStream_socketRead0(JNIEnv *env, jobject this,
|
||||
} else {
|
||||
bufP = BUF;
|
||||
}
|
||||
|
||||
if (timeout) {
|
||||
nread = NET_Timeout(fd, timeout);
|
||||
if (nread <= 0) {
|
||||
if (nread == 0) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
|
||||
"Read timed out");
|
||||
} else if (nread == -1) {
|
||||
if (errno == EBADF) {
|
||||
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Socket closed");
|
||||
} else if (errno == ENOMEM) {
|
||||
JNU_ThrowOutOfMemoryError(env, "NET_Timeout native heap allocation failed");
|
||||
} else {
|
||||
JNU_ThrowByNameWithMessageAndLastError
|
||||
(env, JNU_JAVANETPKG "SocketException", "select/poll failed");
|
||||
}
|
||||
}
|
||||
nread = NET_ReadWithTimeout(env, fd, bufP, len, timeout);
|
||||
if ((*env)->ExceptionCheck(env)) {
|
||||
if (bufP != BUF) {
|
||||
free(bufP);
|
||||
}
|
||||
return -1;
|
||||
return nread;
|
||||
}
|
||||
} else {
|
||||
nread = NET_Read(fd, bufP, len);
|
||||
}
|
||||
|
||||
nread = NET_Read(fd, bufP, len);
|
||||
|
||||
if (nread <= 0) {
|
||||
if (nread < 0) {
|
||||
|
||||
@ -143,7 +162,6 @@ Java_java_net_SocketInputStream_socketRead0(JNIEnv *env, jobject this,
|
||||
JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
|
||||
"Operation interrupted");
|
||||
break;
|
||||
|
||||
default:
|
||||
JNU_ThrowByNameWithMessageAndLastError
|
||||
(env, JNU_JAVANETPKG "SocketException", "Read failed");
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
#include <netdb.h>
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#ifndef _ALLBSD_SOURCE
|
||||
#include <values.h>
|
||||
@ -1669,3 +1670,18 @@ NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout)
|
||||
|
||||
return timeout;
|
||||
}
|
||||
|
||||
long NET_GetCurrentTime() {
|
||||
struct timeval time;
|
||||
gettimeofday(&time, NULL);
|
||||
return (time.tv_sec * 1000 + time.tv_usec / 1000);
|
||||
}
|
||||
|
||||
int NET_TimeoutWithCurrentTime(int s, long timeout, long currentTime) {
|
||||
return NET_Timeout0(s, timeout, currentTime);
|
||||
}
|
||||
|
||||
int NET_Timeout(int s, long timeout) {
|
||||
long currentTime = (timeout > 0) ? NET_GetCurrentTime() : 0;
|
||||
return NET_Timeout0(s, timeout, currentTime);
|
||||
}
|
||||
|
||||
@ -35,7 +35,11 @@
|
||||
#include <sys/poll.h>
|
||||
|
||||
int NET_Timeout(int s, long timeout);
|
||||
int NET_Timeout0(int s, long timeout, long currentTime);
|
||||
int NET_Read(int s, void* buf, size_t len);
|
||||
int NET_NonBlockingRead(int s, void* buf, size_t len);
|
||||
int NET_TimeoutWithCurrentTime(int s, long timeout, long currentTime);
|
||||
long NET_GetCurrentTime();
|
||||
int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
|
||||
struct sockaddr *from, socklen_t *fromlen);
|
||||
int NET_ReadV(int s, const struct iovec * vector, int count);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user