Skip to content
Permalink
Browse files
8265367: [macos-aarch64] 3 java/net/httpclient/websocket tests fail w…
…ith "IOException: No buffer space available"

Reviewed-by: chegar
  • Loading branch information
dfuch committed May 28, 2021
1 parent 1413f9e commit 24bf35f862e285eeca662b9829901c0f91d247d5
Show file tree
Hide file tree
Showing 14 changed files with 114 additions and 55 deletions.
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1290,6 +1290,14 @@ int getReceiveBufferSize() {
);
}

// used for testing
int getSendBufferSize() {
return Utils.getIntegerNetProperty(
"jdk.httpclient.sendBufferSize",
0 // only set the size if > 0
);
}

// Optimization for reading SSL encrypted data
// --------------------------------------------

@@ -210,7 +210,7 @@ public CompletableFuture<Void> connectAsync(Exchange<?> exchange) {
* On some platforms, a ConnectEvent may be raised and a ConnectionException
* may occur with the message "Connection timed out: no further information"
* before our actual connection timeout has expired. In this case, this
* method will be called with a {@code connect} state of {@code ConnectState.RETRY)
* method will be called with a {@code connect} state of {@code ConnectState.RETRY)}
* and we will retry once again.
* @param connect indicates whether the connection was successful or should be retried
* @param failed the failure if the connection failed
@@ -267,10 +267,23 @@ final FlowTube getConnectionFlow() {
try {
this.chan = SocketChannel.open();
chan.configureBlocking(false);
trySetReceiveBufferSize(client.getReceiveBufferSize());
if (debug.on()) {
int bufsize = getInitialBufferSize();
int bufsize = getSoReceiveBufferSize();
debug.log("Initial receive buffer size is: %d", bufsize);
bufsize = getSoSendBufferSize();
debug.log("Initial send buffer size is: %d", bufsize);
}
if (trySetReceiveBufferSize(client.getReceiveBufferSize())) {
if (debug.on()) {
int bufsize = getSoReceiveBufferSize();
debug.log("Receive buffer size configured: %d", bufsize);
}
}
if (trySetSendBufferSize(client.getSendBufferSize())) {
if (debug.on()) {
int bufsize = getSoSendBufferSize();
debug.log("Send buffer size configured: %d", bufsize);
}
}
chan.setOption(StandardSocketOptions.TCP_NODELAY, true);
// wrap the channel in a Tube for async reading and writing
@@ -280,26 +293,52 @@ final FlowTube getConnectionFlow() {
}
}

private int getInitialBufferSize() {
private int getSoReceiveBufferSize() {
try {
return chan.getOption(StandardSocketOptions.SO_RCVBUF);
} catch(IOException x) {
} catch (IOException x) {
if (debug.on())
debug.log("Failed to get initial receive buffer size on %s", chan);
}
return 0;
}

private int getSoSendBufferSize() {
try {
return chan.getOption(StandardSocketOptions.SO_SNDBUF);
} catch (IOException x) {
if (debug.on())
debug.log("Failed to get initial receive buffer size on %s", chan);
}
return 0;
}

private void trySetReceiveBufferSize(int bufsize) {
private boolean trySetReceiveBufferSize(int bufsize) {
try {
if (bufsize > 0) {
chan.setOption(StandardSocketOptions.SO_RCVBUF, bufsize);
return true;
}
} catch(IOException x) {
} catch (IOException x) {
if (debug.on())
debug.log("Failed to set receive buffer size to %d on %s",
bufsize, chan);
}
return false;
}

private boolean trySetSendBufferSize(int bufsize) {
try {
if (bufsize > 0) {
chan.setOption(StandardSocketOptions.SO_SNDBUF, bufsize);
return true;
}
} catch (IOException x) {
if (debug.on())
debug.log("Failed to set send buffer size to %d on %s",
bufsize, chan);
}
return false;
}

@Override
@@ -610,11 +610,6 @@ java/net/MulticastSocket/SetGetNetworkInterfaceTest.java 8219083 windows-

java/net/ServerSocket/AcceptInheritHandle.java 8211854 aix-ppc64


java/net/httpclient/websocket/PendingBinaryPongClose.java 8265367 macosx-aarch64
java/net/httpclient/websocket/PendingBinaryPingClose.java 8265367 macosx-aarch64
java/net/httpclient/websocket/PendingPongBinaryClose.java 8265367 macosx-aarch64

java/net/MulticastSocket/Promiscuous.java 8265369 macosx-aarch64

############################################################################
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -43,7 +43,6 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import static java.net.http.HttpClient.newHttpClient;
import static org.testng.Assert.assertFalse;

public class BlowupOutputQueue extends PendingOperations {
@@ -103,7 +102,7 @@ protected CompletionStage<?> onPing0(WebSocket webSocket,
return null;
}
};
webSocket = newHttpClient().newWebSocketBuilder()
webSocket = httpClient().newWebSocketBuilder()
.buildAsync(server.getURI(), listener)
.join();
CharBuffer data = CharBuffer.allocate(65536);
@@ -92,6 +92,7 @@ public class DummyWebSocketServer implements Closeable {
private volatile InetSocketAddress address;
private ByteBuffer read = ByteBuffer.allocate(16384);
private final CountDownLatch readReady = new CountDownLatch(1);
private volatile int receiveBufferSize;

private static class Credentials {
private final String name;
@@ -217,6 +218,11 @@ public ByteBuffer read() throws InterruptedException {
return read.duplicate().asReadOnlyBuffer().flip();
}

public void setReceiveBufferSize(int bufsize) {
assert ssc == null : "Must configure before calling open()";
this.receiveBufferSize = bufsize;
}

public void open() throws IOException {
err.println("Starting");
if (!started.compareAndSet(false, true)) {
@@ -225,6 +231,15 @@ public void open() throws IOException {
ssc = ServerSocketChannel.open();
try {
ssc.configureBlocking(true);
var bufsize = receiveBufferSize;
if (bufsize > 0) {
err.printf("Configuring receive buffer size to %d%n", bufsize);
try {
ssc.setOption(StandardSocketOptions.SO_RCVBUF, bufsize);
} catch (IOException x) {
err.printf("Failed to configure receive buffer size to %d%n", bufsize);
}
}
ssc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
address = (InetSocketAddress) ssc.getLocalAddress();
thread.start();
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -37,8 +37,6 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import static java.net.http.HttpClient.Builder.NO_PROXY;
import static java.net.http.HttpClient.newBuilder;

public class PendingBinaryPingClose extends PendingOperations {

@@ -51,7 +49,7 @@ public void pendingBinaryPingClose(boolean last) throws Exception {
repeatable(() -> {
server = Support.notReadingServer();
server.open();
webSocket = newBuilder().proxy(NO_PROXY).build().newWebSocketBuilder()
webSocket = httpClient().newWebSocketBuilder()
.buildAsync(server.getURI(), new WebSocket.Listener() { })
.join();
ByteBuffer data = ByteBuffer.allocate(65536);
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -51,7 +51,7 @@ public void pendingBinaryPongClose(boolean last) throws Exception {
repeatable(() -> {
server = Support.notReadingServer();
server.open();
webSocket = newBuilder().proxy(NO_PROXY).build().newWebSocketBuilder()
webSocket = httpClient().newWebSocketBuilder()
.buildAsync(server.getURI(), new WebSocket.Listener() { })
.join();
ByteBuffer data = ByteBuffer.allocate(65536);
@@ -21,16 +21,20 @@
* questions.
*/

import org.testng.annotations.AfterTest;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.DataProvider;

import java.io.IOException;
import java.net.http.HttpClient;
import java.net.http.WebSocket;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.function.BooleanSupplier;

import static java.net.http.HttpClient.Builder.NO_PROXY;
import static java.net.http.HttpClient.newBuilder;

/* Common infrastructure for tests that check pending operations */
public class PendingOperations {

@@ -45,8 +49,15 @@ public class PendingOperations {
DummyWebSocketServer server;
WebSocket webSocket;

@AfterTest
protected HttpClient httpClient() {
return newBuilder().proxy(NO_PROXY).build();
}

@AfterMethod
public void cleanup() {
// make sure we have a trace both on System.out and System.err
// to help with diagnosis.
System.out.println("cleanup: Closing server");
System.err.println("cleanup: Closing server");
server.close();
webSocket.abort();
@@ -81,8 +92,8 @@ static boolean isWindows() {

private static final int ITERATIONS = 3;

static void repeatable(Callable<Void> callable,
BooleanSupplier repeatCondition)
void repeatable(Callable<Void> callable,
BooleanSupplier repeatCondition)
throws Exception
{
int iterations = 0;
@@ -101,10 +112,16 @@ static void repeatable(Callable<Void> callable,
if ((isMac || isWindows) && repeat) {
// ## This is loathsome, but necessary because of observed
// ## automagic socket buffer resizing on recent macOS platforms
try { cleanup(); } catch (Throwable x) {}
continue;
} else {
throw e;
}
} finally {
// gives some time to gc to cleanup any resource that might
// be eligible for garbage collection
System.gc();
Thread.sleep(100);
}
} while (iterations <= ITERATIONS);
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -39,8 +39,6 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import static java.net.http.HttpClient.Builder.NO_PROXY;
import static java.net.http.HttpClient.newBuilder;

public class PendingPingBinaryClose extends PendingOperations {

@@ -53,7 +51,7 @@ public void pendingPingBinaryClose(boolean last) throws Exception {
repeatable( () -> {
server = Support.notReadingServer();
server.open();
webSocket = newBuilder().proxy(NO_PROXY).build().newWebSocketBuilder()
webSocket = httpClient().newWebSocketBuilder()
.buildAsync(server.getURI(), new WebSocket.Listener() { })
.join();
ByteBuffer data = ByteBuffer.allocate(125);
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -39,8 +39,6 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import static java.net.http.HttpClient.Builder.NO_PROXY;
import static java.net.http.HttpClient.newBuilder;

public class PendingPingTextClose extends PendingOperations {

@@ -55,9 +53,8 @@ public void pendingPingTextClose(boolean last) throws Exception {
repeatable(() -> {
server = Support.notReadingServer();
server.open();
webSocket = newBuilder().proxy(NO_PROXY).build().newWebSocketBuilder()
.buildAsync(server.getURI(), new WebSocket.Listener() {
})
webSocket = httpClient().newWebSocketBuilder()
.buildAsync(server.getURI(), new WebSocket.Listener() { })
.join();
ByteBuffer data = ByteBuffer.allocate(125);
boolean done = false;
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -39,8 +39,6 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import static java.net.http.HttpClient.Builder.NO_PROXY;
import static java.net.http.HttpClient.newBuilder;

public class PendingPongBinaryClose extends PendingOperations {

@@ -53,7 +51,7 @@ public void pendingPongBinaryClose(boolean last) throws Exception {
repeatable( () -> {
server = Support.notReadingServer();
server.open();
webSocket = newBuilder().proxy(NO_PROXY).build().newWebSocketBuilder()
webSocket = httpClient().newWebSocketBuilder()
.buildAsync(server.getURI(), new WebSocket.Listener() { })
.join();
ByteBuffer data = ByteBuffer.allocate(125);

1 comment on commit 24bf35f

@openjdk-notifier
Copy link

@openjdk-notifier openjdk-notifier bot commented on 24bf35f May 28, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.