diff --git a/src/main/java/org/java_websocket/client/WebSocketClient.java b/src/main/java/org/java_websocket/client/WebSocketClient.java
index 52dbe61e3..cd9e16fc0 100644
--- a/src/main/java/org/java_websocket/client/WebSocketClient.java
+++ b/src/main/java/org/java_websocket/client/WebSocketClient.java
@@ -93,6 +93,11 @@ public abstract class WebSocketClient extends AbstractWebSocket implements Runna
*/
private Thread writeThread;
+ /**
+ * The thread to connect and read message
+ */
+ private Thread connectReadThread;
+
/**
* The draft to use
*/
@@ -239,12 +244,20 @@ public boolean reconnectBlocking() throws InterruptedException {
* @since 1.3.8
*/
private void reset() {
+ Thread current = Thread.currentThread();
+ if (current == writeThread || current == connectReadThread) {
+ throw new IllegalStateException("You cannot initialize a reconnect out of the websocket thread. Use reconnect in another thread to insure a successful cleanup.");
+ }
try {
closeBlocking();
if( writeThread != null ) {
this.writeThread.interrupt();
this.writeThread = null;
}
+ if( connectReadThread != null ) {
+ this.connectReadThread.interrupt();
+ this.connectReadThread = null;
+ }
this.draft.reset();
if( this.socket != null ) {
this.socket.close();
@@ -264,11 +277,11 @@ private void reset() {
* Initiates the websocket connection. This method does not block.
*/
public void connect() {
- if( writeThread != null )
+ if( connectReadThread != null )
throw new IllegalStateException( "WebSocketClient objects are not reuseable" );
- writeThread = new Thread( this );
- writeThread.setName( "WebSocketConnectReadThread-" + writeThread.getId() );
- writeThread.start();
+ connectReadThread = new Thread( this );
+ connectReadThread.setName( "WebSocketConnectReadThread-" + connectReadThread.getId() );
+ connectReadThread.start();
}
/**
@@ -316,7 +329,7 @@ public void closeBlocking() throws InterruptedException {
/**
* Sends text to the connected websocket server.
- *
+ *
* @param text
* The string which will be transmitted.
*/
@@ -326,7 +339,7 @@ public void send( String text ) throws NotYetConnectedException {
/**
* Sends binary data to the connected webSocket server.
- *
+ *
* @param data
* The byte-Array of data to send to the WebSocket server.
*/
@@ -411,8 +424,7 @@ public void run() {
onError( e );
engine.closeConnection( CloseFrame.ABNORMAL_CLOSE, e.getMessage() );
}
- //I have no idea why this was added.
- //assert ( socket.isClosed() );
+ connectReadThread = null;
}
/**
diff --git a/src/test/java/org/java_websocket/issues/AllIssueTests.java b/src/test/java/org/java_websocket/issues/AllIssueTests.java
index 5759d06b5..617262991 100644
--- a/src/test/java/org/java_websocket/issues/AllIssueTests.java
+++ b/src/test/java/org/java_websocket/issues/AllIssueTests.java
@@ -36,7 +36,8 @@
org.java_websocket.issues.Issue256Test.class,
org.java_websocket.issues.Issue661Test.class,
org.java_websocket.issues.Issue666Test.class,
- org.java_websocket.issues.Issue677Test.class
+ org.java_websocket.issues.Issue677Test.class,
+ org.java_websocket.issues.Issue732Test.class
})
/**
* Start all tests for issues
diff --git a/src/test/java/org/java_websocket/issues/Issue732Test.java b/src/test/java/org/java_websocket/issues/Issue732Test.java
new file mode 100644
index 000000000..59266c621
--- /dev/null
+++ b/src/test/java/org/java_websocket/issues/Issue732Test.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2010-2018 Nathan Rajlich
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package org.java_websocket.issues;
+
+import org.java_websocket.WebSocket;
+import org.java_websocket.WebSocketImpl;
+import org.java_websocket.client.WebSocketClient;
+import org.java_websocket.handshake.ClientHandshake;
+import org.java_websocket.handshake.ServerHandshake;
+import org.java_websocket.server.WebSocketServer;
+import org.java_websocket.util.SocketUtil;
+import org.java_websocket.util.ThreadCheck;
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.util.concurrent.CountDownLatch;
+
+import static org.junit.Assert.fail;
+
+public class Issue732Test {
+
+ @Rule
+ public ThreadCheck zombies = new ThreadCheck();
+
+ private CountDownLatch countServerDownLatch = new CountDownLatch(1);
+
+ @Test(timeout = 2000)
+ public void testIssue() throws Exception {
+ int port = SocketUtil.getAvailablePort();
+ final WebSocketClient webSocket = new WebSocketClient(new URI("ws://localhost:" + port)) {
+ @Override
+ public void onOpen(ServerHandshake handshakedata) {
+ try {
+ this.reconnect();
+ Assert.fail("Exception should be thrown");
+ } catch (IllegalStateException e) {
+ //
+ }
+ }
+
+ @Override
+ public void onMessage(String message) {
+ try {
+ this.reconnect();
+ Assert.fail("Exception should be thrown");
+ } catch (IllegalStateException e) {
+ send("hi");
+ }
+ }
+
+ @Override
+ public void onClose(int code, String reason, boolean remote) {
+ try {
+ this.reconnect();
+ Assert.fail("Exception should be thrown");
+ } catch (IllegalStateException e) {
+ //
+ }
+ }
+
+ @Override
+ public void onError(Exception ex) {
+ try {
+ this.reconnect();
+ Assert.fail("Exception should be thrown");
+ } catch (IllegalStateException e) {
+ //
+ }
+ }
+ };
+ WebSocketServer server = new WebSocketServer(new InetSocketAddress(port)) {
+ @Override
+ public void onOpen(WebSocket conn, ClientHandshake handshake) {
+ conn.send("hi");
+ }
+
+ @Override
+ public void onClose(WebSocket conn, int code, String reason, boolean remote) {
+ countServerDownLatch.countDown();
+ }
+
+ @Override
+ public void onMessage(WebSocket conn, String message) {
+ conn.close();
+ }
+
+ @Override
+ public void onError(WebSocket conn, Exception ex) {
+ fail("There should be no onError!");
+ }
+
+ @Override
+ public void onStart() {
+ webSocket.connect();
+ }
+ };
+ server.start();
+ countServerDownLatch.await();
+ server.stop();
+ }
+}