fix(apple): drop Session in a new task (#9478)

Until we implement #3959 for the Apple client, we need to be careful
around how we de-initialise the Rust session. Callback-based designs are
difficult to get right across boundaries because they enable
re-entrances which then lead to runtime errors.

Specifically, freeing the session needs to cleanup the tokio runtime but
that is impossible if the callback is still executed from that exact
runtime. To workaround this, we need to free the session pointer from a
new task.

Moving to #3959 will solve this in a much more intuitive way because we
can ditch the callbacks and instead move to a stream of events that the
host app can consume.

---------

Signed-off-by: Thomas Eizinger <thomas@eizinger.io>
This commit is contained in:
Thomas Eizinger
2025-06-10 09:09:16 +02:00
committed by GitHub
parent f58176a447
commit dce7ffe4f0

View File

@@ -416,15 +416,17 @@ extension Adapter: CallbackHandlerDelegate {
}
func onDisconnect(error: DisconnectError) {
// Immediately invalidate our session pointer to prevent workQueue items from trying to use it.
// Assigning to `nil` will invoke `Drop` on the Rust side.
session = nil
// Since connlib has already shutdown by this point, we queue this callback
// to ensure that we can clean up even if connlib exits before we are done.
workQueue.async { [weak self] in
guard let self = self else { return }
// Immediately invalidate our session pointer to prevent workQueue items from trying to use it.
// Assigning to `nil` will invoke `Drop` on the Rust side.
// This must happen asynchronously and not as part of the callback to allow Rust to break
// cyclic dependencies between the runtime and the task that is executing the callback.
self.session = nil
// If auth expired/is invalid, delete stored token and save the reason why so the GUI can act upon it.
if error.isAuthenticationError() {
do {