From 15742aee3072091f52b5d65102617c656f46402f Mon Sep 17 00:00:00 2001 From: Evgeny Date: Fri, 21 Mar 2025 11:49:59 +0000 Subject: [PATCH] ios: XCode 16 workaround to prevent stack overflow (#5771) * ios: Workaround for stackoverflow with Xcode 16 - Increased stack size to 4MiB - Fix: https://github.com/simplex-chat/simplex-chat/issues/4837 * Remove Main Thread Stack Size Linker Setting Removed the linker setting for the main thread stack size as the main thread is no longer used. * Set Thread Stack Size to 2MiB Set the thread stack size to 2MiB. In my environment, 992KiB worked fine, so increasing the size to more than double should provide sufficient margin. * ios: moving content up when setting emoji on the first message (#5766) * simplify --------- Co-authored-by: ISHIHARA Kazuto Co-authored-by: Avently <7953703+avently@users.noreply.github.com> --- apps/ios/SimpleXChat/API.swift | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/apps/ios/SimpleXChat/API.swift b/apps/ios/SimpleXChat/API.swift index 5e5f047611..e439cd337b 100644 --- a/apps/ios/SimpleXChat/API.swift +++ b/apps/ios/SimpleXChat/API.swift @@ -183,7 +183,9 @@ public func chatResponse(_ s: String) -> ChatResponse { // let p = UnsafeMutableRawPointer.init(mutating: UnsafeRawPointer(cjson)) // let d = Data.init(bytesNoCopy: p, count: strlen(cjson), deallocator: .free) do { - let r = try jsonDecoder.decode(APIResponse.self, from: d) + let r = try callWithLargeStack { + try jsonDecoder.decode(APIResponse.self, from: d) + } return r.resp } catch { logger.error("chatResponse jsonDecoder.decode error: \(error.localizedDescription)") @@ -231,6 +233,32 @@ public func chatResponse(_ s: String) -> ChatResponse { return ChatResponse.response(type: type ?? "invalid", json: json ?? s) } +private let largeStackSize: Int = 2 * 1024 * 1024 + +private func callWithLargeStack(_ f: @escaping () throws -> T) throws -> T { + let semaphore = DispatchSemaphore(value: 0) + var result: Result? + let thread = Thread { + do { + result = .success(try f()) + } catch { + result = .failure(error) + } + semaphore.signal() + } + + thread.stackSize = largeStackSize + thread.qualityOfService = Thread.current.qualityOfService + thread.start() + + semaphore.wait() + + switch result! { + case let .success(r): return r + case let .failure(e): throw e + } +} + private func decodeUser_(_ jDict: NSDictionary) -> UserRef? { if let user_ = jDict["user_"] { try? decodeObject(user_ as Any)