Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EXC_BAD_ACCESS when using opt-level="z" on calling pollFunc() on Swift #2429

Open
chris13524 opened this issue Feb 5, 2025 · 2 comments
Open

Comments

@chris13524
Copy link

chris13524 commented Feb 5, 2025

We are trying to optimize our binary size, and in particular seem to be having an issue with setting opt-level="z" in the cargo profile. Everything builds fine, but at runtime we get this error:

Thread 8: EXC_BAD_ACCESS (code=2, address=0x16fe47240)

We don't seem to have this problem on Kotlin with the same profile configuration.

We also have strip = true enabled which we already know works. We tried removing this and removing other optimization flags, but it didn't help the error. Interestingly, the address in the error doesn't seem to change either with the build tweaks we've tried.

Any ideas on how to debug this further? I wouldn't think opt-level="z" would affect more than performance. Thinking it's probably a bug in UniFFI, or an incompatibility with opt-level="z" that should be documented.

fileprivate func uniffiRustCallAsync<F, T>(
    rustFutureFunc: () -> UInt64,
    pollFunc: (UInt64, @escaping UniffiRustFutureContinuationCallback, UInt64) -> (),
    completeFunc: (UInt64, UnsafeMutablePointer<RustCallStatus>) -> F,
    freeFunc: (UInt64) -> (),
    liftFunc: (F) throws -> T,
    errorHandler: ((RustBuffer) throws -> Swift.Error)?
) async throws -> T {
    // Make sure to call the ensure init function since future creation doesn't have a
    // RustCallStatus param, so doesn't use makeRustCall()
    uniffiEnsureUniffiYttriumInitialized()
    let rustFuture = rustFutureFunc()
    defer {
        freeFunc(rustFuture)
    }
    var pollResult: Int8;
    repeat {
        pollResult = await withUnsafeContinuation {
            pollFunc( // ================== Error here ==================
                rustFuture,
                uniffiFutureContinuationCallback,
                uniffiContinuationHandleMap.insert(obj: $0)
            )
        }
    } while pollResult != UNIFFI_RUST_FUTURE_POLL_READY

    return try liftFunc(makeRustCall(
        { completeFunc(rustFuture, $0) },
        errorHandler: errorHandler
    ))
}
@Iskander508
Copy link

Iskander508 commented Feb 13, 2025

We ran into the exact same problem. For us it happened regardless optimization settings on both iOS (swift) and Android (kotlin). After investigating we found the cause. It was an enormous allocation of memory on stack (1MB) in rust code:
let mut buf = [0; SIZE];
We resolved it by moving the allocation onto heap (using Vec). Maybe double-check your code doesn't do something similar (stack overflow, ...).

@chris13524
Copy link
Author

Thanks for the thought @Iskander508! I will check for things like that 🤔 I also got some ideas from ChatGPT.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants