Threads with classic lock-based synchronization in SwiftUI in Xcode 16

Hi, I am stuck moving one of my projects from Xcode 15 to Xcode 16. This is a SwiftUI application that uses in some places classic Threads and locks/conditions for synchronization. I was hoping that in Swift 5 mode, I could compile and run this app also with Xcode 16 so that I can start migrating it towards Swift 6.

Unfortunately, my application crashes via EXC_BREAKPOINT (code=1, subcode=0x1800eb31c) whenever some blocking operation e.g. condition.wait() or DispatchQueue.main.sync { ... } is invoked from within the same module (I haven't seen this happening for frameworks that use the same code that I linked in dynamically). I have copied an abstraction below that I am using, to give an example of the kind of code I am talking about. I have verified that Swift 5 is used, "strict concurrency checking" is set to "minimal", etc.

I have not found a workaround and thus, I'm curious to hear if others were facing similar challenges? Any hints on how to proceed are welcome.

Thanks, Matthias

Example abstraction that is used in my app. It's needed because I have synchronous computations that require a large stack. It's crashing whenever condition.wait() is executed.

public final class TaskSerializer: Thread {
  
  /// Condition to synchronize access to `tasks`.
  private let condition = NSCondition()
  
  /// The tasks queue.
  private var tasks = [() -> Void]()
  
  public init(stackSize: Int = 8_388_608, qos: QualityOfService = .userInitiated) {
    super.init()
    self.stackSize = stackSize
    self.qualityOfService = qos
  }
  
  /// Don't call directly; this is the main method of the serializer thread.
  public override func main() {
    super.main()
    while !self.isCancelled {
      self.condition.lock()
      while self.tasks.isEmpty {
        if self.isCancelled {
          self.condition.unlock()
          return
        }
        self.condition.wait()
      }
      let task = self.tasks.removeFirst()
      self.condition.unlock()
      task()
    }
    self.condition.lock()
    self.tasks.removeAll()
    self.condition.unlock()
  }
  
  /// Schedule a task in this serializer thread.
  public func schedule(task: @escaping () -> Void) {
    self.condition.lock()
    self.tasks.append(task)
    self.condition.signal()
    self.condition.unlock()
  }
}
Threads with classic lock-based synchronization in SwiftUI in Xcode 16
 
 
Q