golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
124k stars 17.67k forks source link

x/mobile: iOS Simulator crash when running under Rosetta #61475

Open arantes555 opened 1 year ago

arantes555 commented 1 year ago

When running an iOS app on Simulator under Rosetta (sometimes necessary when certain libraries do not support arm64 simulator), importing an xcframework built with gomobile makes the app freeze on boot, makes it crash when trying to stop it from XCode, and leaves the Simulator in a broken state.

This happend with a library we are working on, then I reproduced it with a minimal gomobile library test project ( https://github.com/arantes555/gomobile_test ).

When building this project with gomobile bind -target=ios -prefix=GomobileTest -v -o=./GomobileTest.xcframework ./mobile_sdk, then importing the resulting .xcframework in a freshly created template iOS app (both swift and objc), the app works correctly on Intel mac, works correctly on M1 mac using arm64 Simulator, but crashes on M1 mac using rosetta Simulator. Here is a repo with an iOS app which reproduces the issue : https://github.com/arantes555/gomobile_ios_crash_repro_app

When running on rosetta, the app freezes on start, and does not do anything. Then, when trying to use the Stop button from XCode, I get the following error in the XCode console:

assertion failed [gTaskSuspended]: cannot resume thread when task not suspended (DebugServer.cpp:230 thread_resume) Message from debugger: failed to send the k packet

Also, I get a crash report window with an error stack including these lines:

Coalition: com.apple.CoreSimulator.SimDevice.8813C46E-A23C-47F2-A621-0510CA85B316 [72815]
Responsible Process: SimulatorTrampoline [68471]

The full error report is in this file : simulator crash.txt

Lastly, after this, the simulator is left in a weird state where it does not respond to the XCode commands, and when closing it I get the error contained in this file : simulator-crash-2.txt

I am aware this is probably a bug in Rosetta itself, and I also reported it to Apple, but maybe the Go community can fix it on our side.

heschi commented 1 year ago

cc @golang/ios

arantes555 commented 1 year ago

After some investigation, it seems this also happens on a CGo library built for iOS.

cherrymui commented 1 year ago

As you mentioned, the assertion failure looks like a bug in Rosetta. Thank you for reporting to Apple.

For a workaround, you may try setting the environment variable GODEUBG=asyncpreemptoff=1 and don't send signals to you program. In the past Rosetta is known to have a number of bugs related to signal handling (which are fixed, but new bug could appear).

arantes555 commented 1 year ago

Hello @cherrymui . Thanks for your answer. Looks like setting the env var at runtime works ! Thank you very much ! Looks like there may be a few bugs related to signal handling left in Rosetta ... Is this something that could be solved on Go's side, or only on Apple's side? Just in case, here is my precise setup:

If there's anything else I can do to help diagnose this?

BTW, I didn't send any signal manually, except starting / stopping the app through XCode.

cherrymui commented 1 year ago

Setting the environment variable is probably the best workaround. I don't think we're going to disable signals by default on the Go side for this bug. As signals can arrive at any point, it doesn't seem easy to have a more limited workaround. Given the assertion text

assertion failed [gTaskSuspended]: cannot resume thread when task not suspended (DebugServer.cpp:230 thread_resume) Message from debugger: failed to send the k packet

It looks like the Rosetta runtime is probably in some inconsistent state, perhaps due to a race condition.

Are you running under some debugger? (LLDB? Within Xcode?) Maybe that adds another layer of complexity. If so maybe you could try not running under debugger?

I think Apple usually fixes bug like this in a reasonable amount of time, so I hope it will get fixed soon. If you could write a C reproducer (perhaps sending a bunch of signals to itself or to another thread in the same process), that may speed up Apple's fix. Thanks.

arantes555 commented 1 year ago

To reproduce the bug, I simply:

I am not doing anything special to attach a debugger, not sure if XCode attaches a debugger by default.

I am sorry but I definitely don't have the knowledge to write a C repro case for this.

The env var workaround works for me for the moment. I guess the ball is in Apple's court.

Feel free to close the issue if you believe there is nothing more to do on Go's side. Or leave it open if you prefer until I update you about Apple's answer to my report.

Thanks again for your help!

ezoushen commented 12 months ago

This thread saved my day!!! For those also suffering from this issue, here's how to set up the workaround in your Xcode

Screenshot 2023-11-17 at 2 58 14 PM