Skip to content

Commit 34d3df2

Browse files
Fixed a few issues with session startup and close
1 parent 01bd116 commit 34d3df2

File tree

2 files changed

+76
-34
lines changed

2 files changed

+76
-34
lines changed

src/main/java/net/dv8tion/jda/core/requests/WebSocketClient.java

+44-26
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,21 @@ public WebSocketClient(JDAImpl api)
115115
this.shardInfo = api.getShardInfo();
116116
this.shouldReconnect = api.isAutoReconnect();
117117
this.connectNode = new StartingNode();
118-
api.getSessionController().appendSession(connectNode);
118+
try
119+
{
120+
api.getSessionController().appendSession(connectNode);
121+
}
122+
catch (RuntimeException | Error e)
123+
{
124+
LOG.error("Failed to append new session to session controller queue. Shutting down!", e);
125+
this.api.setStatus(JDA.Status.SHUTDOWN);
126+
this.api.getEventManager().handle(
127+
new ShutdownEvent(api, OffsetDateTime.now(), 1006));
128+
if (e instanceof RuntimeException)
129+
throw (RuntimeException) e;
130+
else
131+
throw (Error) e;
132+
}
119133
}
120134

121135
public JDA getJDA()
@@ -396,17 +410,20 @@ private JSONObject newVoiceOpen(AudioManager manager, VoiceChannel channel)
396410

397411
public void close()
398412
{
399-
socket.sendClose(1000);
413+
if (socket != null)
414+
socket.sendClose(1000);
400415
}
401416

402417
public void close(int code)
403418
{
404-
socket.sendClose(code);
419+
if (socket != null)
420+
socket.sendClose(code);
405421
}
406422

407423
public void close(int code, String reason)
408424
{
409-
socket.sendClose(code, reason);
425+
if (socket != null)
426+
socket.sendClose(code, reason);
410427
}
411428

412429
public synchronized void shutdown()
@@ -552,10 +569,19 @@ else if (closeCode != null)
552569
if (isInvalidate)
553570
invalidate(); // 1000 means our session is dropped so we cannot resume
554571
api.getEventManager().handle(new DisconnectEvent(api, serverCloseFrame, clientCloseFrame, closedByServer, OffsetDateTime.now()));
555-
if (sessionId == null)
572+
try
573+
{
574+
if (sessionId == null)
575+
queueReconnect();
576+
else // if resume is possible
577+
reconnect();
578+
}
579+
catch (InterruptedException e)
580+
{
581+
LOG.error("Failed to resume due to interrupted thread", e);
582+
invalidate();
556583
queueReconnect();
557-
else // if resume is possible
558-
reconnect();
584+
}
559585
}
560586
}
561587

@@ -578,7 +604,7 @@ protected void queueReconnect()
578604
}
579605
}
580606

581-
protected void reconnect()
607+
protected void reconnect() throws InterruptedException
582608
{
583609
reconnect(false, true);
584610
}
@@ -592,7 +618,7 @@ protected void reconnect()
592618
* @param shouldHandleIdentify
593619
* whether SessionReconnectQueue already handled an IDENTIFY rate limit for this session
594620
*/
595-
public void reconnect(boolean callFromQueue, boolean shouldHandleIdentify)
621+
public void reconnect(boolean callFromQueue, boolean shouldHandleIdentify) throws InterruptedException
596622
{
597623
if (callFromQueue && api.getContextMap() != null)
598624
api.getContextMap().forEach(MDC::put);
@@ -613,23 +639,15 @@ public void reconnect(boolean callFromQueue, boolean shouldHandleIdentify)
613639
}
614640
while (shouldReconnect)
615641
{
616-
try
617-
{
618-
api.setStatus(JDA.Status.WAITING_TO_RECONNECT);
619-
if (handleIdentifyRateLimit && shouldHandleIdentify)
620-
{
621-
LOG.error("Encountered IDENTIFY (OP {}) Rate Limit! Waiting {} seconds before trying again!",
622-
WebSocketCode.IDENTIFY, IDENTIFY_DELAY);
623-
Thread.sleep(IDENTIFY_DELAY * 1000);
624-
}
625-
else
626-
{
627-
Thread.sleep(reconnectTimeoutS * 1000);
628-
}
629-
handleIdentifyRateLimit = false;
630-
api.setStatus(JDA.Status.ATTEMPTING_TO_RECONNECT);
631-
}
632-
catch (InterruptedException ignored) {}
642+
api.setStatus(JDA.Status.WAITING_TO_RECONNECT);
643+
int delay = IDENTIFY_DELAY;
644+
if (handleIdentifyRateLimit && shouldHandleIdentify)
645+
LOG.error("Encountered IDENTIFY (OP {}) Rate Limit! Waiting {} seconds before trying again!", WebSocketCode.IDENTIFY, IDENTIFY_DELAY);
646+
else
647+
delay = reconnectTimeoutS;
648+
Thread.sleep(delay * 1000);
649+
handleIdentifyRateLimit = false;
650+
api.setStatus(JDA.Status.ATTEMPTING_TO_RECONNECT);
633651
LOG.warn("Attempting to reconnect!");
634652
try
635653
{

src/main/java/net/dv8tion/jda/core/utils/SessionControllerAdapter.java

+32-8
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package net.dv8tion.jda.core.utils;
1818

19+
import com.neovisionaries.ws.client.OpeningHandshakeException;
1920
import net.dv8tion.jda.core.AccountType;
2021
import net.dv8tion.jda.core.JDA;
2122
import net.dv8tion.jda.core.exceptions.AccountTypeException;
@@ -25,6 +26,7 @@
2526
import net.dv8tion.jda.core.requests.Route;
2627
import net.dv8tion.jda.core.utils.tuple.Pair;
2728
import org.json.JSONObject;
29+
import org.slf4j.Logger;
2830

2931
import javax.security.auth.login.LoginException;
3032
import java.util.Queue;
@@ -34,6 +36,7 @@
3436

3537
public class SessionControllerAdapter implements SessionController
3638
{
39+
protected static final Logger log = JDALogger.getLog(SessionControllerAdapter.class);
3740
protected final Object lock = new Object();
3841
protected Queue<SessionConnectNode> connectQueue;
3942
protected AtomicLong globalRatelimit;
@@ -169,6 +172,12 @@ public QueueWorker(long delay)
169172
{
170173
super("SessionControllerAdapter-Worker");
171174
this.delay = delay;
175+
super.setUncaughtExceptionHandler(this::handleFailure);
176+
}
177+
178+
protected void handleFailure(Thread thread, Throwable exception)
179+
{
180+
log.error("Worker has failed with throwable!", exception);
172181
}
173182

174183
@Override
@@ -185,8 +194,19 @@ public void run()
185194
}
186195
catch (InterruptedException ex)
187196
{
188-
JDALogger.getLog(SessionControllerAdapter.class).error("Unable to backoff", ex);
197+
log.error("Unable to backoff", ex);
189198
}
199+
processQueue();
200+
synchronized (lock)
201+
{
202+
workerHandle = null;
203+
if (!connectQueue.isEmpty())
204+
runWorker();
205+
}
206+
}
207+
208+
protected void processQueue()
209+
{
190210
while (!connectQueue.isEmpty())
191211
{
192212
SessionConnectNode node = connectQueue.poll();
@@ -199,18 +219,22 @@ public void run()
199219
if (this.delay > 0)
200220
Thread.sleep(this.delay);
201221
}
222+
catch (IllegalStateException e)
223+
{
224+
Throwable t = e.getCause();
225+
if (t instanceof OpeningHandshakeException)
226+
log.error("Failed opening handshake, appending to queue. Message: {}", e.getMessage());
227+
else
228+
log.error("Failed to establish connection for a node, appending to queue", e);
229+
appendSession(node);
230+
}
202231
catch (InterruptedException e)
203232
{
204-
JDALogger.getLog(SessionControllerAdapter.class).error("Failed to run node", e);
233+
log.error("Failed to run node", e);
205234
appendSession(node);
235+
return; // caller should start a new thread
206236
}
207237
}
208-
synchronized (lock)
209-
{
210-
workerHandle = null;
211-
if (!connectQueue.isEmpty())
212-
runWorker();
213-
}
214238
}
215239
}
216240
}

0 commit comments

Comments
 (0)