Post

Replies

Boosts

Views

Activity

Deadlock in thread_suspend() under Rosetta
The thread_suspend() Mach API will sometimes deadlock when called from an Intel process running on a Mac with Apple Silicon. This can be replicated by the following code in a unit test class, and using Xcode's "Run Repeatedly..." functionality to run the test 1000 times: - (void)testThreadDeadlock { dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); const int threadCount = 1000; for (int i = 0; i < threadCount; i++) { [NSThread detachNewThreadSelector:@selector(waitForSemaphore:) toTarget:self withObject:semaphore]; } thread_t thisThread = mach_thread_self(); thread_t *threads = NULL; mach_msg_type_number_t numThreads = 0; task_threads(mach_task_self(), &threads, &numThreads); for (mach_msg_type_number_t i = 0; i < numThreads; i++) { if (threads[i] != thisThread) { thread_suspend(threads[i]); // <--- this call will sometimes deadlock } } for (mach_msg_type_number_t i = 0; i < numThreads; i++) { if (threads[i] != thisThread) { thread_resume(threads[i]); } } vm_deallocate(mach_task_self(), threads, sizeof(*threads) * numThreads); for (int i = 0; i < threadCount; i++) { dispatch_semaphore_signal(semaphore); } } - (void)waitForSemaphore:(dispatch_semaphore_t)semaphore { dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); } Oddly, the deadlock does not appear to happen if the threads are spawned with pthread_create() instead of +[NSThread detachNewThreadSelector:toTarget:withObject:] This deadlock only happens under Rosetta. On Intel Macs or when running the ARM slice on Apple Silicon no deadlock can be reprodiced with this code. A similar deadlock can also occur in thread_info() if it is used after the threads are suspended. This has also been submitted via Feedback Assistant - FB9922280
0
0
498
Feb ’22