So I spent some time today investigating why ctrl-C doesn't quit QEMU on MacOS. This is a specific instance of a general issue which is that signals like SIGINT and SIGTERM don't end up in the os-posix.c termination handler like they should.
(1) MacOS debug tools are deeply unhelpful here: (a) running under gdb() breaks sigwait() (b) dtrace probes for signal-send/signal-discard don't actually cover all the cases of a signal being sent, so neither trigger when you do a 'kill -TERM' of QEMU in this state (2) Weird Stuff seems to be happening: it turns out the the reason these signals don't work is that the main thread ends up with them blocked, so with no thread with SIGTERM &c unblocked they just get endlessly ignored. I ended up adding logging printf()s all over the place which print the thread ID and the current state of SIGTERM (blocked/unblocked). The interesting bit is in this logging: sigdebug: about to pthread_mutex_lock: TID 0x7fff7c1c1180: SIGTERM: unblocked sigdebug: done pthread_mutex_lock: TID 0x7fff7c1c1180: SIGTERM: blocked which is around the pthread_mutex_lock() call in qemu_mutex_lock(). We go in with SIGTERM unblocked, we come out with it locked... dtruss says: 13176/0x6f8c35: __pthread_sigmask(0x3, 0x0, 0x7FFF59F311AC) = 0 0 13176/0x6f8c35: write_nocancel(0x1, "sigdebug: about to pthread_mutex_lock: TID 0x7fff7c1c1180: SIGTERM: unblocked\n\0", 0x4E) = 78 0 13176/0x6f8c53: sigreturn(0x10BB07878, 0x1E, 0xAB5BB6621A84A222) = 0 Err#-2 13176/0x6f8c53: sigprocmask(0x3, 0x10BB07DB0, 0x0) = 0x0 0 13176/0x6f8c53: sigreturn(0x0, 0x80000000, 0x0) = 0 0 13176/0x6f8c53: sigprocmask(0x1, 0x0, 0x10BB07DD0) = 0x0 0 13176/0x6f8c53: sigaltstack(0x0, 0x10BB07DC0, 0x0) = 0 0 13176/0x6f8c53: psynch_cvwait(0x106714B78, 0x100000100, 0x0) = 0 0 13176/0x6f8c35: psynch_mutexwait(0x106714BA8, 0x543, 0x300) = 1283 0 13176/0x6f8c35: __pthread_sigmask(0x3, 0x0, 0x7FFF59F311AC) = 0 0 13176/0x6f8c35: write_nocancel(0x1, "sigdebug: done pthread_mutex_lock: TID 0x7fff7c1c1180: SIGTERM: blocked\n\0", 0x48) = 72 0 What seems to happen is that the other thread nips in and does the sigreturn/sigprocmask/sigaltstack stuff, and it's messing with the signal mask for the whole process. (dtruss also tell me 0x6f8c53 is the TCG CPU thread.) However I have no idea where the sigaltstack comes from, since we're using the gthread coroutine backend, not the sigaltstack one. Anybody got any ideas? (I may look further at this tomorrow...) -- PMM