提交 efffd359 编写于 作者: A alanb

6989190: SO_SNDBUF/SO_RCVBUF limits should only be checked when setsockopt fails (sol)

Reviewed-by: chegar, michaelm
上级 b8b55293
......@@ -363,17 +363,20 @@ void ThrowUnknownHostExceptionWithGaiError(JNIEnv *env,
const char* hostname,
int gai_error)
{
int size;
char *buf;
const char *format = "%s: %s";
const char *error_string =
(gai_strerror_ptr == NULL) ? NULL : (*gai_strerror_ptr)(gai_error);
if (error_string == NULL)
error_string = "unknown error";
int size = strlen(format) + strlen(hostname) + strlen(error_string) + 2;
char *buf = (char *) malloc(size);
size = strlen(format) + strlen(hostname) + strlen(error_string) + 2;
buf = (char *) malloc(size);
if (buf) {
jstring s;
sprintf(buf, format, hostname, error_string);
jstring s = JNU_NewStringPlatform(env, buf);
s = JNU_NewStringPlatform(env, buf);
if (s != NULL) {
jobject x = JNU_NewObjectByName(env,
"java/net/UnknownHostException",
......@@ -1203,19 +1206,26 @@ NET_SetSockOpt(int fd, int level, int opt, const void *arg,
}
/*
* SOL_SOCKET/{SO_SNDBUF,SO_RCVBUF} - On Solaris need to
* ensure that value is <= max_buf as otherwise we get
* an invalid argument.
* SOL_SOCKET/{SO_SNDBUF,SO_RCVBUF} - On Solaris we may need to clamp
* the value when it exceeds the system limit.
*/
#ifdef __solaris__
if (level == SOL_SOCKET) {
if (opt == SO_SNDBUF || opt == SO_RCVBUF) {
int sotype, arglen;
int *bufsize, maxbuf;
int ret;
/* Attempt with the original size */
ret = setsockopt(fd, level, opt, arg, len);
if ((ret == 0) || (ret == -1 && errno != ENOBUFS))
return ret;
/* Exceeded system limit so clamp and retry */
if (!init_max_buf) {
tcp_max_buf = getParam("/dev/tcp", "tcp_max_buf", 64*1024);
udp_max_buf = getParam("/dev/udp", "udp_max_buf", 64*1024);
tcp_max_buf = getParam("/dev/tcp", "tcp_max_buf", 1024*1024);
udp_max_buf = getParam("/dev/udp", "udp_max_buf", 2048*1024);
init_max_buf = 1;
}
......
......@@ -29,7 +29,9 @@
import java.nio.channels.*;
import java.net.*;
import static java.net.StandardSocketOption.*;
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicReference;
......@@ -39,6 +41,7 @@ public class Basic {
public static void main(String[] args) throws Exception {
testBind();
testAccept();
testSocketOptions();
}
static void testBind() throws Exception {
......@@ -131,4 +134,39 @@ public class Basic {
}
}
static void testSocketOptions() throws Exception {
System.out.println("-- socket options --");
AsynchronousServerSocketChannel ch = AsynchronousServerSocketChannel.open();
try {
// check supported options
Set<SocketOption<?>> options = ch.supportedOptions();
if (!options.contains(SO_REUSEADDR))
throw new RuntimeException("SO_REUSEADDR should be supported");
if (!options.contains(SO_RCVBUF))
throw new RuntimeException("SO_RCVBUF should be supported");
// allowed to change when not bound
ch.setOption(SO_RCVBUF, 256*1024); // can't check
int before = ch.getOption(SO_RCVBUF);
int after = ch.setOption(SO_RCVBUF, Integer.MAX_VALUE).getOption(SO_RCVBUF);
if (after < before)
throw new RuntimeException("setOption caused SO_RCVBUF to decrease");
ch.setOption(SO_REUSEADDR, true);
checkOption(ch, SO_REUSEADDR, true);
ch.setOption(SO_REUSEADDR, false);
checkOption(ch, SO_REUSEADDR, false);
} finally {
ch.close();
}
}
static void checkOption(AsynchronousServerSocketChannel ch,
SocketOption name, Object expectedValue)
throws IOException
{
Object value = ch.getOption(name);
if (!value.equals(expectedValue))
throw new RuntimeException("value not as expected");
}
}
......@@ -121,8 +121,20 @@ public class Basic {
AsynchronousSocketChannel ch = AsynchronousSocketChannel.open()
.setOption(SO_RCVBUF, 128*1024)
.setOption(SO_SNDBUF, 128*1024)
.setOption(SO_REUSEADDR, true)
.bind(new InetSocketAddress(0));
.setOption(SO_REUSEADDR, true);
// check SO_SNDBUF/SO_RCVBUF limits
int before, after;
before = ch.getOption(SO_SNDBUF);
after = ch.setOption(SO_SNDBUF, Integer.MAX_VALUE).getOption(SO_SNDBUF);
if (after < before)
throw new RuntimeException("setOption caused SO_SNDBUF to decrease");
before = ch.getOption(SO_RCVBUF);
after = ch.setOption(SO_RCVBUF, Integer.MAX_VALUE).getOption(SO_RCVBUF);
if (after < before)
throw new RuntimeException("setOption caused SO_RCVBUF to decrease");
ch.bind(new InetSocketAddress(0));
// default values
if ((Boolean)ch.getOption(SO_KEEPALIVE))
......
......@@ -68,8 +68,17 @@ public class SocketOptionTests {
checkOption(dc, SO_BROADCAST, true);
dc.setOption(SO_BROADCAST, false);
checkOption(dc, SO_BROADCAST, false);
dc.setOption(SO_SNDBUF, 16*1024); // can't check
dc.setOption(SO_RCVBUF, 16*1024); // can't check
dc.setOption(SO_SNDBUF, 128*1024); // can't check
dc.setOption(SO_RCVBUF, 128*1024); // can't check
int before, after;
before = dc.getOption(SO_SNDBUF);
after = dc.setOption(SO_SNDBUF, Integer.MAX_VALUE).getOption(SO_SNDBUF);
if (after < before)
throw new RuntimeException("setOption caused SO_SNDBUF to decrease");
before = dc.getOption(SO_RCVBUF);
after = dc.setOption(SO_RCVBUF, Integer.MAX_VALUE).getOption(SO_RCVBUF);
if (after < before)
throw new RuntimeException("setOption caused SO_RCVBUF to decrease");
dc.setOption(SO_REUSEADDR, true);
checkOption(dc, SO_REUSEADDR, true);
dc.setOption(SO_REUSEADDR, false);
......
......@@ -56,6 +56,10 @@ public class SocketOptionTests {
// allowed to change when not bound
ssc.setOption(SO_RCVBUF, 256*1024); // can't check
int before = ssc.getOption(SO_RCVBUF);
int after = ssc.setOption(SO_RCVBUF, Integer.MAX_VALUE).getOption(SO_RCVBUF);
if (after < before)
throw new RuntimeException("setOption caused SO_RCVBUF to decrease");
ssc.setOption(SO_REUSEADDR, true);
checkOption(ssc, SO_REUSEADDR, true);
ssc.setOption(SO_REUSEADDR, false);
......
......@@ -70,6 +70,15 @@ public class SocketOptionTests {
checkOption(sc, SO_KEEPALIVE, false);
sc.setOption(SO_SNDBUF, 128*1024); // can't check
sc.setOption(SO_RCVBUF, 256*1024); // can't check
int before, after;
before = sc.getOption(SO_SNDBUF);
after = sc.setOption(SO_SNDBUF, Integer.MAX_VALUE).getOption(SO_SNDBUF);
if (after < before)
throw new RuntimeException("setOption caused SO_SNDBUF to decrease");
before = sc.getOption(SO_RCVBUF);
after = sc.setOption(SO_RCVBUF, Integer.MAX_VALUE).getOption(SO_RCVBUF);
if (after < before)
throw new RuntimeException("setOption caused SO_RCVBUF to decrease");
sc.setOption(SO_REUSEADDR, true);
checkOption(sc, SO_REUSEADDR, true);
sc.setOption(SO_REUSEADDR, false);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册