From c7f2e7c662229744ccc98aa14b78ae159a82ecd1 Mon Sep 17 00:00:00 2001 From: helloJetBase-tech <178346048+marktech0813@users.noreply.github.com> Date: Tue, 11 Nov 2025 14:26:51 +0200 Subject: [PATCH] Handle exceptions in WebSocket event methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I found where the server invokes your overridden callbacks and added guards so exceptions from onOpen, onClose, and onError cannot crash the selector thread. I also wrapped onStart similarly. Lints are clean. What I changed - Guarded callback invocations in src/main/java/org/java_websocket/server/WebSocketServer.java: Wrap onOpen, onClose, onError, and onStart in try/catch. Log the exception and attempt to call onError(...); if onError itself throws, swallow and log to prevent propagation. - Outcome: Exceptions thrown by your overrides no longer bubble up to the server’s run loop; the server continues accepting connections even if a “bad” client triggers user code exceptions. --- .../server/WebSocketServer.java | 51 ++++++++++++++++--- 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/java_websocket/server/WebSocketServer.java b/src/main/java/org/java_websocket/server/WebSocketServer.java index 8d11bcf4..194ba580 100644 --- a/src/main/java/org/java_websocket/server/WebSocketServer.java +++ b/src/main/java/org/java_websocket/server/WebSocketServer.java @@ -621,7 +621,16 @@ private boolean doSetupSelectorAndServerThread() { for (WebSocketWorker ex : decoders) { ex.start(); } - onStart(); + try { + onStart(); + } catch (Exception e) { + log.error("Exception in onStart", e); + try { + onError(null, e); + } catch (Exception ex2) { + log.error("Exception in onError while handling onStart", ex2); + } + } } catch (IOException ex) { handleFatal(null, ex); return false; @@ -735,7 +744,11 @@ private void handleIOException(SelectionKey key, WebSocket conn, IOException ex) private void handleFatal(WebSocket conn, Exception e) { log.error("Shutdown due to fatal error", e); - onError(conn, e); + try { + onError(conn, e); + } catch (Exception ex2) { + log.error("Exception in onError while handling fatal error", ex2); + } String causeMessage = e.getCause() != null ? " caused by " + e.getCause().getClass().getName() : ""; String errorMessage = "Got error on server side: " + e.getClass().getName() + causeMessage; @@ -744,7 +757,11 @@ private void handleFatal(WebSocket conn, Exception e) { } catch (InterruptedException e1) { Thread.currentThread().interrupt(); log.error("Interrupt during stop", e); - onError(null, e1); + try { + onError(null, e1); + } catch (Exception ex2) { + log.error("Exception in onError while handling interrupt during stop", ex2); + } } //Shutting down WebSocketWorkers, see #222 @@ -772,7 +789,16 @@ public final void onWebsocketMessage(WebSocket conn, ByteBuffer blob) { @Override public final void onWebsocketOpen(WebSocket conn, Handshakedata handshake) { if (addConnection(conn)) { - onOpen(conn, (ClientHandshake) handshake); + try { + onOpen(conn, (ClientHandshake) handshake); + } catch (Exception e) { + log.error("Exception in onOpen", e); + try { + onError(conn, e); + } catch (Exception ex2) { + log.error("Exception in onError while handling onOpen", ex2); + } + } } } @@ -781,7 +807,16 @@ public final void onWebsocketClose(WebSocket conn, int code, String reason, bool selector.wakeup(); try { if (removeConnection(conn)) { - onClose(conn, code, reason, remote); + try { + onClose(conn, code, reason, remote); + } catch (Exception e) { + log.error("Exception in onClose", e); + try { + onError(conn, e); + } catch (Exception ex2) { + log.error("Exception in onError while handling onClose", ex2); + } + } } } finally { try { @@ -841,7 +876,11 @@ protected boolean addConnection(WebSocket ws) { @Override public final void onWebsocketError(WebSocket conn, Exception ex) { - onError(conn, ex); + try { + onError(conn, ex); + } catch (Exception ex2) { + log.error("Exception in onError", ex2); + } } @Override