提交 1848a278 编写于 作者: V vtewari

8075484: SocketInputStream.socketRead0 can hang even with soTimeout set

Reviewed-by: chegar, dsamersoff, msheppar, clanger
上级 584b6277
/* /*
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, SAP SE and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -328,6 +329,10 @@ int NET_Read(int s, void* buf, size_t len) { ...@@ -328,6 +329,10 @@ int NET_Read(int s, void* buf, size_t len) {
BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) ); 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) { int NET_ReadV(int s, const struct iovec * vector, int count) {
BLOCKING_IO_RETURN_INT( s, readv(s, vector, count) ); BLOCKING_IO_RETURN_INT( s, readv(s, vector, count) );
} }
...@@ -429,8 +434,8 @@ int NET_Select(int s, fd_set *readfds, fd_set *writefds, ...@@ -429,8 +434,8 @@ int NET_Select(int s, fd_set *readfds, fd_set *writefds,
* Auto restarts with adjusted timeout if interrupted by * Auto restarts with adjusted timeout if interrupted by
* signal other than our wakeup signal. * signal other than our wakeup signal.
*/ */
int NET_Timeout(int s, long timeout) { int NET_Timeout0(int s, long timeout, long currentTime) {
long prevtime = 0, newtime; long prevtime = currentTime, newtime;
struct timeval t; struct timeval t;
fdEntry_t *fdEntry = getFdEntry(s); fdEntry_t *fdEntry = getFdEntry(s);
...@@ -442,14 +447,6 @@ int NET_Timeout(int s, long timeout) { ...@@ -442,14 +447,6 @@ int NET_Timeout(int s, long timeout) {
return -1; 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(;;) { for(;;) {
struct pollfd pfd; struct pollfd pfd;
int rv; int rv;
......
/* /*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -52,6 +52,42 @@ Java_java_net_SocketInputStream_init(JNIEnv *env, jclass cls) { ...@@ -52,6 +52,42 @@ Java_java_net_SocketInputStream_init(JNIEnv *env, jclass cls) {
IO_fd_fdID = NET_GetFileDescriptorID(env); IO_fd_fdID = NET_GetFileDescriptorID(env);
} }
#if !defined(__solaris__)
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, "java/net/SocketTimeoutException", "Read timed out");
} else if (result == -1) {
if (errno == EBADF) {
JNU_ThrowByName(env, "java/net/SocketException", "Socket closed");
} else if (errno == ENOMEM) {
JNU_ThrowOutOfMemoryError(env, "NET_Timeout native heap allocation failed");
} else {
JNU_ThrowByNameWithMessageAndLastError
(env, "java/net/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;
}
#endif
/* /*
* Class: java_net_SocketInputStream * Class: java_net_SocketInputStream
* Method: socketRead0 * Method: socketRead0
...@@ -99,6 +135,7 @@ Java_java_net_SocketInputStream_socketRead0(JNIEnv *env, jobject this, ...@@ -99,6 +135,7 @@ Java_java_net_SocketInputStream_socketRead0(JNIEnv *env, jobject this,
bufP = BUF; bufP = BUF;
} }
#if defined(__solaris__)
if (timeout) { if (timeout) {
nread = NET_Timeout(fd, timeout); nread = NET_Timeout(fd, timeout);
if (nread <= 0) { if (nread <= 0) {
...@@ -126,7 +163,19 @@ Java_java_net_SocketInputStream_socketRead0(JNIEnv *env, jobject this, ...@@ -126,7 +163,19 @@ Java_java_net_SocketInputStream_socketRead0(JNIEnv *env, jobject this,
} }
nread = NET_Read(fd, bufP, len); nread = NET_Read(fd, bufP, len);
#else
if (timeout) {
nread = NET_ReadWithTimeout(env, fd, bufP, len, timeout);
if ((*env)->ExceptionCheck(env)) {
if (bufP != BUF) {
free(bufP);
}
return nread;
}
} else {
nread = NET_Read(fd, bufP, len);
}
#endif
if (nread <= 0) { if (nread <= 0) {
if (nread < 0) { if (nread < 0) {
......
/* /*
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -292,6 +292,10 @@ int NET_Read(int s, void* buf, size_t len) { ...@@ -292,6 +292,10 @@ int NET_Read(int s, void* buf, size_t len) {
BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) ); 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) { int NET_ReadV(int s, const struct iovec * vector, int count) {
BLOCKING_IO_RETURN_INT( s, readv(s, vector, count) ); BLOCKING_IO_RETURN_INT( s, readv(s, vector, count) );
} }
...@@ -344,8 +348,8 @@ int NET_Select(int s, fd_set *readfds, fd_set *writefds, ...@@ -344,8 +348,8 @@ int NET_Select(int s, fd_set *readfds, fd_set *writefds,
* Auto restarts with adjusted timeout if interrupted by * Auto restarts with adjusted timeout if interrupted by
* signal other than our wakeup signal. * signal other than our wakeup signal.
*/ */
int NET_Timeout(int s, long timeout) { int NET_Timeout0(int s, long timeout, long currentTime) {
long prevtime = 0, newtime; long prevtime = currentTime, newtime;
struct timeval t, *tp = &t; struct timeval t, *tp = &t;
fd_set fds; fd_set fds;
fd_set* fdsp = NULL; fd_set* fdsp = NULL;
...@@ -366,9 +370,6 @@ int NET_Timeout(int s, long timeout) { ...@@ -366,9 +370,6 @@ int NET_Timeout(int s, long timeout) {
*/ */
if (timeout > 0) { if (timeout > 0) {
/* Timed */ /* Timed */
struct timeval now;
gettimeofday(&now, NULL);
prevtime = now.tv_sec * 1000 + now.tv_usec / 1000;
t.tv_sec = timeout / 1000; t.tv_sec = timeout / 1000;
t.tv_usec = (timeout % 1000) * 1000; t.tv_usec = (timeout % 1000) * 1000;
} else if (timeout < 0) { } else if (timeout < 0) {
......
/* /*
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -273,6 +273,10 @@ int NET_Read(int s, void* buf, size_t len) { ...@@ -273,6 +273,10 @@ int NET_Read(int s, void* buf, size_t len) {
BLOCKING_IO_RETURN_INT( s, recv(s, buf, len, 0) ); 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) { int NET_ReadV(int s, const struct iovec * vector, int count) {
BLOCKING_IO_RETURN_INT( s, readv(s, vector, count) ); BLOCKING_IO_RETURN_INT( s, readv(s, vector, count) );
} }
...@@ -324,8 +328,8 @@ int NET_Select(int s, fd_set *readfds, fd_set *writefds, ...@@ -324,8 +328,8 @@ int NET_Select(int s, fd_set *readfds, fd_set *writefds,
* Auto restarts with adjusted timeout if interrupted by * Auto restarts with adjusted timeout if interrupted by
* signal other than our wakeup signal. * signal other than our wakeup signal.
*/ */
int NET_Timeout(int s, long timeout) { int NET_Timeout0(int s, long timeout, long currentTime) {
long prevtime = 0, newtime; long prevtime = currentTime, newtime;
struct timeval t; struct timeval t;
fdEntry_t *fdEntry = getFdEntry(s); fdEntry_t *fdEntry = getFdEntry(s);
...@@ -337,14 +341,6 @@ int NET_Timeout(int s, long timeout) { ...@@ -337,14 +341,6 @@ int NET_Timeout(int s, long timeout) {
return -1; 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(;;) { for(;;) {
struct pollfd pfd; struct pollfd pfd;
int rv; int rv;
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <netdb.h> #include <netdb.h>
#include <stdlib.h> #include <stdlib.h>
#include <dlfcn.h> #include <dlfcn.h>
#include <sys/time.h>
#ifndef _ALLBSD_SOURCE #ifndef _ALLBSD_SOURCE
#include <values.h> #include <values.h>
...@@ -1661,3 +1662,20 @@ NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout) ...@@ -1661,3 +1662,20 @@ NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout)
return timeout; return timeout;
} }
#if !defined(__solaris__)
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);
}
#endif
...@@ -47,9 +47,13 @@ ...@@ -47,9 +47,13 @@
close subroutine does not return until the select call returns. close subroutine does not return until the select call returns.
... ...
*/ */
#if defined(__linux__) || defined(MACOSX) || defined (_AIX) #if !defined(__solaris__)
extern int NET_Timeout(int s, long timeout); extern int NET_Timeout(int s, long timeout);
extern int NET_Timeout0(int s, long timeout, long currentTime);
extern int NET_Read(int s, void* buf, size_t len); extern int NET_Read(int s, void* buf, size_t len);
extern int NET_NonBlockingRead(int s, void* buf, size_t len);
extern int NET_TimeoutWithCurrentTime(int s, long timeout, long currentTime);
extern long NET_GetCurrentTime();
extern int NET_RecvFrom(int s, void *buf, int len, unsigned int flags, extern int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
struct sockaddr *from, int *fromlen); struct sockaddr *from, int *fromlen);
extern int NET_ReadV(int s, const struct iovec * vector, int count); extern int NET_ReadV(int s, const struct iovec * vector, int count);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册