From 568b02c0f1040fd9445f7b3fbea4abb54aaa5960 Mon Sep 17 00:00:00 2001 From: chall37 Date: Mon, 19 Jan 2026 22:11:26 -0800 Subject: [PATCH] Fix deadlock in whilePaused when re-entered via nested runloop Check iTermGCD.joined at entry to avoid scheduling a second semaphore dance when the mutation queue is already waiting. --- sources/TokenExecutor.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sources/TokenExecutor.swift b/sources/TokenExecutor.swift index 12c23003ca..7b2b243997 100644 --- a/sources/TokenExecutor.swift +++ b/sources/TokenExecutor.swift @@ -409,6 +409,12 @@ private class TokenExecutorImpl { // Runs block synchronously while token executor is stopped. func whilePaused(_ block: () -> (), onExecutorQueue: Bool) { dispatchPrecondition(condition: .onQueue(.main)) + if iTermGCD.joined { + // Already joined (likely re-entrant via a nested runloop). Avoid deadlock by reusing + // the existing join instead of creating a new one. + block() + return + } if gDebugLogging.boolValue { DLog("Incr pending pauses if \(iTermPreferences.maximizeThroughput())") } var unpauser = iTermPreferences.maximizeThroughput() ? nil : TokenExecutor.globalPause()