Skip to content

Commit 7700b91

Browse files
authored
Merge pull request TooTallNate#1 from Serpion-ua/Issue-1160
Issue-1160 Added java.lang.Error handling in WebSocketImpl and WebSocketServer
2 parents c2d0873 + d9537d6 commit 7700b91

File tree

3 files changed

+183
-2
lines changed

3 files changed

+183
-2
lines changed

src/main/java/org/java_websocket/WebSocketImpl.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
package org.java_websocket;
2727

2828
import java.io.IOException;
29+
import java.io.PrintWriter;
30+
import java.io.StringWriter;
2931
import java.net.InetSocketAddress;
3032
import java.nio.ByteBuffer;
3133
import java.nio.channels.ByteChannel;
@@ -410,6 +412,14 @@ private void decodeFrames(ByteBuffer socketBuffer) {
410412
log.error("Closing due to invalid data in frame", e);
411413
wsl.onWebsocketError(this, e);
412414
close(e);
415+
} catch (VirtualMachineError | ThreadDeath | LinkageError e) {
416+
log.error("Got fatal error during frame processing");
417+
throw e;
418+
} catch (Error e) {
419+
log.error("Closing web socket due to an error during frame processing");
420+
Exception exception = new Exception(e.getMessage());
421+
wsl.onWebsocketError(this, exception);
422+
close(CloseFrame.UNEXPECTED_CONDITION, exception.getMessage());
413423
}
414424
}
415425

src/main/java/org/java_websocket/server/WebSocketServer.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,8 +1079,20 @@ public void run() {
10791079
}
10801080
} catch (InterruptedException e) {
10811081
Thread.currentThread().interrupt();
1082-
} catch (RuntimeException e) {
1083-
handleFatal(ws, e);
1082+
} catch (VirtualMachineError | ThreadDeath | LinkageError e) {
1083+
if (ws != null) {
1084+
ws.close();
1085+
}
1086+
log.error("Got fatal error in worker thread" + getName());
1087+
Exception exception = new Exception(e.getMessage());
1088+
handleFatal(ws, exception);
1089+
} catch (Throwable e) {
1090+
log.error("Uncaught exception in thread {}: {}", getName(), e);
1091+
if (ws != null) {
1092+
Exception exception = new Exception(e.getMessage());
1093+
onWebsocketError(ws, exception);
1094+
ws.close();
1095+
}
10841096
}
10851097
}
10861098

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
package org.java_websocket.issues;
2+
3+
import org.java_websocket.WebSocket;
4+
import org.java_websocket.client.WebSocketClient;
5+
import org.java_websocket.handshake.ClientHandshake;
6+
import org.java_websocket.handshake.ServerHandshake;
7+
import org.java_websocket.server.WebSocketServer;
8+
import org.java_websocket.util.SocketUtil;
9+
import org.junit.Assert;
10+
import org.junit.Test;
11+
12+
import java.net.InetSocketAddress;
13+
import java.net.URI;
14+
import java.nio.ByteBuffer;
15+
import java.util.concurrent.CountDownLatch;
16+
import java.util.concurrent.atomic.AtomicInteger;
17+
18+
public class Issue1160Test {
19+
private final CountDownLatch countServerStart = new CountDownLatch(1);
20+
21+
static class TestClient extends WebSocketClient {
22+
private final CountDownLatch onCloseLatch;
23+
24+
public TestClient(URI uri, CountDownLatch latch) {
25+
super(uri);
26+
onCloseLatch = latch;
27+
}
28+
29+
@Override
30+
public void onOpen(ServerHandshake handshakedata) {
31+
}
32+
33+
@Override
34+
public void onMessage(String message) {
35+
}
36+
37+
@Override
38+
public void onClose(int code, String reason, boolean remote) {
39+
onCloseLatch.countDown();
40+
}
41+
42+
@Override
43+
public void onError(Exception ex) {
44+
}
45+
}
46+
47+
48+
@Test(timeout = 5000)
49+
public void nonFatalErrorShallBeHandledByServer() throws Exception {
50+
final AtomicInteger isServerOnErrorCalledCounter = new AtomicInteger(0);
51+
52+
int port = SocketUtil.getAvailablePort();
53+
WebSocketServer server = new WebSocketServer(new InetSocketAddress(port)) {
54+
@Override
55+
public void onOpen(WebSocket conn, ClientHandshake handshake) {
56+
}
57+
58+
@Override
59+
public void onClose(WebSocket conn, int code, String reason, boolean remote) {
60+
}
61+
62+
@Override
63+
public void onMessage(WebSocket conn, ByteBuffer message) {
64+
throw new Error("Some error");
65+
}
66+
67+
@Override
68+
public void onMessage(WebSocket conn, String message) {
69+
throw new Error("Some error");
70+
}
71+
72+
@Override
73+
public void onError(WebSocket conn, Exception ex) {
74+
isServerOnErrorCalledCounter.incrementAndGet();
75+
}
76+
77+
@Override
78+
public void onStart() {
79+
countServerStart.countDown();
80+
}
81+
};
82+
83+
84+
server.setConnectionLostTimeout(10);
85+
server.start();
86+
countServerStart.await();
87+
88+
URI uri = new URI("ws://localhost:" + port);
89+
90+
int CONNECTION_COUNT = 3;
91+
for (int i = 0; i < CONNECTION_COUNT; i++) {
92+
CountDownLatch countClientDownLatch = new CountDownLatch(1);
93+
WebSocketClient client = new TestClient(uri, countClientDownLatch);
94+
client.setConnectionLostTimeout(10);
95+
96+
client.connectBlocking();
97+
client.send(new byte[100]);
98+
countClientDownLatch.await();
99+
client.closeBlocking();
100+
}
101+
102+
Assert.assertEquals(CONNECTION_COUNT, isServerOnErrorCalledCounter.get());
103+
104+
server.stop();
105+
}
106+
107+
@Test(timeout = 5000)
108+
public void fatalErrorShallNotBeHandledByServer() throws Exception {
109+
int port = SocketUtil.getAvailablePort();
110+
111+
final CountDownLatch countServerDownLatch = new CountDownLatch(1);
112+
WebSocketServer server = new WebSocketServer(new InetSocketAddress(port)) {
113+
@Override
114+
public void onOpen(WebSocket conn, ClientHandshake handshake) {
115+
}
116+
117+
@Override
118+
public void onClose(WebSocket conn, int code, String reason, boolean remote) {
119+
countServerDownLatch.countDown();
120+
}
121+
122+
@Override
123+
public void onMessage(WebSocket conn, ByteBuffer message) {
124+
throw new OutOfMemoryError("Some error");
125+
}
126+
127+
@Override
128+
public void onMessage(WebSocket conn, String message) {
129+
throw new OutOfMemoryError("Some error");
130+
}
131+
132+
@Override
133+
public void onError(WebSocket conn, Exception ex) {
134+
}
135+
136+
@Override
137+
public void onStart() {
138+
countServerStart.countDown();
139+
}
140+
};
141+
142+
143+
server.setConnectionLostTimeout(10);
144+
server.start();
145+
countServerStart.await();
146+
147+
URI uri = new URI("ws://localhost:" + port);
148+
149+
CountDownLatch countClientDownLatch = new CountDownLatch(1);
150+
WebSocketClient client = new TestClient(uri, countClientDownLatch);
151+
client.setConnectionLostTimeout(10);
152+
153+
client.connectBlocking();
154+
client.send(new byte[100]);
155+
countClientDownLatch.await();
156+
countServerDownLatch.await();
157+
Assert.assertTrue(countClientDownLatch.getCount() == 0 && countServerDownLatch.getCount() == 0);
158+
}
159+
}

0 commit comments

Comments
 (0)