-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Race Conditions when closing server, port is still bound #879
Comments
Hello! |
Thanks. I gave it a try. Same result. |
I saw a maybe-related issue here: #877 (comment) |
Maybe this test is related as well: #877 (comment) |
Not really related, the way I did the test back then sucked and broke when I updated to use SLF4J. |
Was not able to reproduce with the websocket client... |
so the code in the issue didn't reproduce for you? darn. |
@Jonahss I was simple not able to reproduce it with the java websocket client when I tried to reproduce it quickly. No need to close it yet ;) |
Oh okay. it's not a terrible issue for me. Most people must not be encountering it. I was able to solve for my use case by adding a short wait. Although inelegant, it doesn't really harm the code, as it's a small project with little use so far. |
port is still bound, i have to wait for dozens of seconds. :) |
Fix ConcurrentModificationException found during the investigation of TooTallNate#879
I tried again with a new pc and differend jre version (12) and still was not able to reproduce it. Best regards, |
Maybe my observation can help on this:
However,
I am using the native JavaScript WebSocket client |
Would WebSocketServer.stop(timeout) be a better option for you ? Do be honest, only a good project where I can reproduce it can help... |
I wrote this test but didn't get it to fail. public class Issue879Test {
private static final int NUM_SERVERS_CREATED = 2;
private static final int NUM_CLIENTS = 10;
private static final AtomicInteger SERVERS_STARTED_COUNT = new AtomicInteger(0);
@Test()
public void testIssue() throws Exception {
int port = SocketUtil.getAvailablePort();
for (int i = 0; i < NUM_SERVERS_CREATED; i++) {
WebSocketServer server = new Issue879Server(new InetSocketAddress(port));
server.start();
for (int j = 0; j < NUM_CLIENTS; j++) {
WebSocketClient client = new Issue879Client(new URI("ws://localhost:" + port));
client.connectBlocking();
assert client.isOpen();
}
server.stop();
}
assert SERVERS_STARTED_COUNT.get() == NUM_SERVERS_CREATED;
}
private static class Issue879Server extends WebSocketServer {
Issue879Server(InetSocketAddress address) {
super(address);
}
@Override
public void onOpen(WebSocket conn, ClientHandshake handshake) {
}
@Override
public void onClose(WebSocket conn, int code, String reason, boolean remote) {
}
@Override
public void onMessage(WebSocket conn, String message) {
}
@Override
public void onError(WebSocket conn, Exception ex) {
assert false;
}
@Override
public void onStart() {
SERVERS_STARTED_COUNT.incrementAndGet();
}
}
private static class Issue879Client extends WebSocketClient {
Issue879Client(URI serverUri) {
super(serverUri);
}
@Override
public void onOpen(ServerHandshake handshakedata) {
}
@Override
public void onMessage(String message) {
}
@Override
public void onClose(int code, String reason, boolean remote) {
}
@Override
public void onError(Exception ex) {
}
}
} |
@marci4 Indeed, I have not. Also, it solves my issue. To anyone stumbling accross this in the future: Here is the according wiki section which I did not see before... Sorry about that! |
I recently upgraded to 1.4.0 (from 1.3.4) and also witnessed that the websocket port remained in TIME_WAIT after a close(), preventing to reopen the port immediately. I added a call to NB: the problem was occurring on Linux but not on Windows |
Seems like I have the same issue, reproducible using the client and server from the same (this) library. See this test: https://github.com/Smarteon/loxone-java/blob/master/src/test/groovy/cz/smarteon/loxone/LoxoneWebSocketIT.groovy#L114 I tried also adding |
@jimirocks so it is os and Java version dependant? Sounds like an issue in the JVM? |
@marci4 it happens on all linuxes and JVMs I use (raspbian, ubuntu, fedora, jvm8-11), what differs is the rate. So my guess it's not necessarily the JVM issue. |
@jimirocks was never able to reproduce it on windows. |
@marci4 well, my reproducer is 100% successful using JDK11 on ubuntu. |
I updated to 1.5.1 and got the same problem in Android. Thanks for the library and your effort |
@marci4 I am also encountered this problem and I used setReuseAddr(true) to solve this issue by as it mentioned in this thread. Is this correct solution for the problem ? |
Just a heads up. I had the same issue across JVM restarts: Create a WebSocketServer, connect from a browser client (localhost, Firefox), close the WebSocketServer and the whole JVM instance, and then starting it again said the address was already bound. Using WebSocketServer::setReuseAddr(true) seems to fix it. Thanks! |
SO_REUSEADDR allows your server to bind to an address which is in a |
I had the same issue with a server running on Android. |
I can confirm this worked for me on Android. |
Describe the bug
Hello! I'm not a Java expert, but was happy to find this easy websocket implementation.
I've run into a race condition with closing a server, and immediately opening a new server on the same port.
This came up as part of my unit tests. Each test passes in isolation, but when they run quickly one after another, well, they started to throw
java.net.BindException: Address already in use
exceptions.I've built a really great repro case for you! I was really embarrassed to add a
Thread.sleep()
call after myserver.close()
call, so I created a repro.The following code will run just fine. This is the naiive case of starting a server, closing it, and starting another server. The issue comes up in the particular way that my client is spamming the server to create new connections.
So that code passes.
BUT. When I have a server spamming connections, the code above will sometimes pass, sometimes fail with my "Address already in use error" and sometimes fail with a
ClosedSelectorException
.Here's the code which spams the connection. I did my best to help here, but I had to pull the code out of a Python script which was running, I couldn't repro with a java client.
(use python3 and install the
websockets
module)Expected behavior
Well, my unit tests should be able to start servers on the same port as a previously stopped server without adding a 500ms sleep in between.
Debug log
The the debug log (set the log level to
TRACE
) to help explain your problem.^I could do this if you walk me through how.
Environment(please complete the following information):
The text was updated successfully, but these errors were encountered: