Make asyncMainDrainQueue noreturn

CFRunLoopRun returns once it finishes, though the kernel may clean us up
before we get there. We effectively have a race condition between the
kernel cleaning us up and returning from a never returning function.

Small programs likely get cleaned up before reaching the ud2 instruction
emitted after the never returning function in swift, so they don't
notice, but programs of a sufficient size do. At that size, the program
will crash after what the programmer expects to be the end of their
program.
This commit is contained in:
Evan Wilde
2021-03-19 12:33:26 -07:00
parent 129fca6f0a
commit b0b4cb67a1
2 changed files with 6 additions and 3 deletions

View File

@@ -744,6 +744,7 @@ void swift::swift_task_asyncMainDrainQueue() {
abort();
pfndispatch_main();
exit(0);
#else
// CFRunLoop is not available on non-Darwin targets. Foundation has an
// implementation, but CoreFoundation is not meant to be exposed. We can only
@@ -752,8 +753,10 @@ void swift::swift_task_asyncMainDrainQueue() {
#if defined(__APPLE__)
auto runLoop =
reinterpret_cast<void (*)(void)>(dlsym(RTLD_DEFAULT, "CFRunLoopRun"));
if (runLoop)
return runLoop();
if (runLoop) {
runLoop();
exit(0);
}
#endif
dispatch_main();