Connect from connect thread. Avoids stack overflow

This commit is contained in:
2023-11-30 14:59:36 -05:00
parent 9ded3dfdc6
commit 145bf4d7b1

View File

@@ -28,12 +28,14 @@ class Obs(
/** Queue of requests to run. */ /** Queue of requests to run. */
private val q:BlockingQueue<Req> = LinkedBlockingQueue() private val q:BlockingQueue<Req> = LinkedBlockingQueue()
/** Backoff on errors. */
private val backoff = Backoff()
/** Flag to set when closed to stop queue poll loop. */ /** Flag to set when closed to stop queue poll loop. */
private val closed = AtomicBoolean(false) private val closed = AtomicBoolean(false)
/**
* Flag set when we start trying to connect, unset when disconnected.
* Used to determine if we should reconnect on controller error.
*/
private val connectingOrConnected = AtomicBoolean(false)
/** /**
* Flag to set when connected, unset when disconnected. * Flag to set when connected, unset when disconnected.
* Used to determine if we should reconnect on controller error. * Used to determine if we should reconnect on controller error.
@@ -69,9 +71,21 @@ class Obs(
addShutdownHook { addShutdownHook {
close() close()
} }
// connect() blocks until OBS is up, so fork it. // Thread that connects if we are not connected/connecting.
thread(name="obs-init-connect", isDaemon=true, start=true) { thread(name="obs-connect", isDaemon=true, start=true) {
while(!closed.get()) {
if (connectingOrConnected.compareAndSet(false,true)) {
log.debug("Not closed, not connected. Try to connect...")
try {
// Only call connect from here; if you try to call connect from [onControllerError] or [onDisconnect]
// eventually you will get stack overflow.
controller.connect() controller.connect()
} catch (e:Exception) {
log.warn("failed to connect: ${e.message}", e)
}
}
Thread.sleep(connectionTimeout.toLong() * 1000L) // in case the error was immediate
}
} }
} }
@@ -82,11 +96,10 @@ class Obs(
private fun onControllerError(e:ReasonThrowable) { private fun onControllerError(e:ReasonThrowable) {
log.debug("controller error - ${e.reason}",e.throwable) log.debug("controller error - ${e.reason}",e.throwable)
if (!closed.get() && !connected.get()) { // If we are not connected, a controller error means that connection failed and we will not connect.
log.debug("connection failed") // If we are connected, it does not mean we are/will be disconnected.
backoff.backoff() if (!connected.get()) {
log.debug("reconnect after connection failed...") connectingOrConnected.set(false)
controller.connect()
} }
} }
private fun onCommError(e:ReasonThrowable) { private fun onCommError(e:ReasonThrowable) {
@@ -94,12 +107,8 @@ class Obs(
} }
private fun onDisconnect() { private fun onDisconnect() {
log.debug("disconnected") log.debug("disconnected")
connectingOrConnected.set(false)
connected.set(false) connected.set(false)
if (! closed.get()) {
backoff.backoff()
log.debug("reconnect after disconnected..")
controller.connect()
}
} }
private fun onReady() { private fun onReady() {