I read several Linux book and tutorials about signals, they all say kernel handles signals at the timing that kernel transitions from kernel to user mode. This makes total sense, until I saw and experimented the following code:
>cat sig_timing.c
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdbool.h>
volatile bool done = false;
static void sig_handler(int signo)
{
printf("Received signal %d (%s), current errno:%s\n", signo, strsignal(signo), strerror(errno));
done = true;
}
int main(int argc, char **argv)
{
signal(SIGALRM, sig_handler);
alarm(3);
while (!done) {
strlen("Hello World!");
}
return 0;
}
>gcc sig_timing.c
>./a.out
Received signal 14 (Alarm clock), current errno:Success
So the main function enters endless loop after registering the signal, the loop does not invoke any system call, so there is no chance to enter kernel, then there is no transition from kernel to user mode, then there should be no chance to invoke signal handler, right?
Later on, the talk host explained what's going on (I adapted a bit):
Sender kernel thread sends inter-cpu message to cause hardware interrupt on CPU running target process, causing it to enter the kernel to handle the interrupt, and return to user mode.
I am not so convinced: this explanation seems saying the signal sender and signal receiver run at 2 CPU hardware threads. But what about CPU without hyper threading? The process runs just at one CPU thread. In that case, does the signal get chance to get handled while user land code runs an endless loop?