Skip to content

Commit 9918a55

Browse files
authored
Merge pull request TooTallNate#739 from marci4/Reconnect
Exception when using reconnect in websocket thread
2 parents dfe3e21 + 4e61424 commit 9918a55

File tree

3 files changed

+149
-9
lines changed

3 files changed

+149
-9
lines changed

src/main/java/org/java_websocket/client/WebSocketClient.java

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ public abstract class WebSocketClient extends AbstractWebSocket implements Runna
9393
*/
9494
private Thread writeThread;
9595

96+
/**
97+
* The thread to connect and read message
98+
*/
99+
private Thread connectReadThread;
100+
96101
/**
97102
* The draft to use
98103
*/
@@ -239,12 +244,20 @@ public boolean reconnectBlocking() throws InterruptedException {
239244
* @since 1.3.8
240245
*/
241246
private void reset() {
247+
Thread current = Thread.currentThread();
248+
if (current == writeThread || current == connectReadThread) {
249+
throw new IllegalStateException("You cannot initialize a reconnect out of the websocket thread. Use reconnect in another thread to insure a successful cleanup.");
250+
}
242251
try {
243252
closeBlocking();
244253
if( writeThread != null ) {
245254
this.writeThread.interrupt();
246255
this.writeThread = null;
247256
}
257+
if( connectReadThread != null ) {
258+
this.connectReadThread.interrupt();
259+
this.connectReadThread = null;
260+
}
248261
this.draft.reset();
249262
if( this.socket != null ) {
250263
this.socket.close();
@@ -264,11 +277,11 @@ private void reset() {
264277
* Initiates the websocket connection. This method does not block.
265278
*/
266279
public void connect() {
267-
if( writeThread != null )
280+
if( connectReadThread != null )
268281
throw new IllegalStateException( "WebSocketClient objects are not reuseable" );
269-
writeThread = new Thread( this );
270-
writeThread.setName( "WebSocketConnectReadThread-" + writeThread.getId() );
271-
writeThread.start();
282+
connectReadThread = new Thread( this );
283+
connectReadThread.setName( "WebSocketConnectReadThread-" + connectReadThread.getId() );
284+
connectReadThread.start();
272285
}
273286

274287
/**
@@ -316,7 +329,7 @@ public void closeBlocking() throws InterruptedException {
316329

317330
/**
318331
* Sends <var>text</var> to the connected websocket server.
319-
*
332+
*
320333
* @param text
321334
* The string which will be transmitted.
322335
*/
@@ -326,7 +339,7 @@ public void send( String text ) throws NotYetConnectedException {
326339

327340
/**
328341
* Sends binary <var> data</var> to the connected webSocket server.
329-
*
342+
*
330343
* @param data
331344
* The byte-Array of data to send to the WebSocket server.
332345
*/
@@ -411,8 +424,7 @@ public void run() {
411424
onError( e );
412425
engine.closeConnection( CloseFrame.ABNORMAL_CLOSE, e.getMessage() );
413426
}
414-
//I have no idea why this was added.
415-
//assert ( socket.isClosed() );
427+
connectReadThread = null;
416428
}
417429

418430
/**

src/test/java/org/java_websocket/issues/AllIssueTests.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@
3636
org.java_websocket.issues.Issue256Test.class,
3737
org.java_websocket.issues.Issue661Test.class,
3838
org.java_websocket.issues.Issue666Test.class,
39-
org.java_websocket.issues.Issue677Test.class
39+
org.java_websocket.issues.Issue677Test.class,
40+
org.java_websocket.issues.Issue732Test.class
4041
})
4142
/**
4243
* Start all tests for issues
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/*
2+
* Copyright (c) 2010-2018 Nathan Rajlich
3+
*
4+
* Permission is hereby granted, free of charge, to any person
5+
* obtaining a copy of this software and associated documentation
6+
* files (the "Software"), to deal in the Software without
7+
* restriction, including without limitation the rights to use,
8+
* copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the
10+
* Software is furnished to do so, subject to the following
11+
* conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be
14+
* included in all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17+
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18+
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19+
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20+
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21+
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22+
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23+
* OTHER DEALINGS IN THE SOFTWARE.
24+
*/
25+
26+
package org.java_websocket.issues;
27+
28+
import org.java_websocket.WebSocket;
29+
import org.java_websocket.WebSocketImpl;
30+
import org.java_websocket.client.WebSocketClient;
31+
import org.java_websocket.handshake.ClientHandshake;
32+
import org.java_websocket.handshake.ServerHandshake;
33+
import org.java_websocket.server.WebSocketServer;
34+
import org.java_websocket.util.SocketUtil;
35+
import org.java_websocket.util.ThreadCheck;
36+
import org.junit.Assert;
37+
import org.junit.Rule;
38+
import org.junit.Test;
39+
40+
import java.net.InetSocketAddress;
41+
import java.net.URI;
42+
import java.util.concurrent.CountDownLatch;
43+
44+
import static org.junit.Assert.fail;
45+
46+
public class Issue732Test {
47+
48+
@Rule
49+
public ThreadCheck zombies = new ThreadCheck();
50+
51+
private CountDownLatch countServerDownLatch = new CountDownLatch(1);
52+
53+
@Test(timeout = 2000)
54+
public void testIssue() throws Exception {
55+
int port = SocketUtil.getAvailablePort();
56+
final WebSocketClient webSocket = new WebSocketClient(new URI("ws://localhost:" + port)) {
57+
@Override
58+
public void onOpen(ServerHandshake handshakedata) {
59+
try {
60+
this.reconnect();
61+
Assert.fail("Exception should be thrown");
62+
} catch (IllegalStateException e) {
63+
//
64+
}
65+
}
66+
67+
@Override
68+
public void onMessage(String message) {
69+
try {
70+
this.reconnect();
71+
Assert.fail("Exception should be thrown");
72+
} catch (IllegalStateException e) {
73+
send("hi");
74+
}
75+
}
76+
77+
@Override
78+
public void onClose(int code, String reason, boolean remote) {
79+
try {
80+
this.reconnect();
81+
Assert.fail("Exception should be thrown");
82+
} catch (IllegalStateException e) {
83+
//
84+
}
85+
}
86+
87+
@Override
88+
public void onError(Exception ex) {
89+
try {
90+
this.reconnect();
91+
Assert.fail("Exception should be thrown");
92+
} catch (IllegalStateException e) {
93+
//
94+
}
95+
}
96+
};
97+
WebSocketServer server = new WebSocketServer(new InetSocketAddress(port)) {
98+
@Override
99+
public void onOpen(WebSocket conn, ClientHandshake handshake) {
100+
conn.send("hi");
101+
}
102+
103+
@Override
104+
public void onClose(WebSocket conn, int code, String reason, boolean remote) {
105+
countServerDownLatch.countDown();
106+
}
107+
108+
@Override
109+
public void onMessage(WebSocket conn, String message) {
110+
conn.close();
111+
}
112+
113+
@Override
114+
public void onError(WebSocket conn, Exception ex) {
115+
fail("There should be no onError!");
116+
}
117+
118+
@Override
119+
public void onStart() {
120+
webSocket.connect();
121+
}
122+
};
123+
server.start();
124+
countServerDownLatch.await();
125+
server.stop();
126+
}
127+
}

0 commit comments

Comments
 (0)