I'm experiencing signals' reaction, being used with threads. I know printf family functions are not signal-safe functions but for the simplicity I use. The following is said that
When a signal is delivered to a multithreaded process that has established a signal handler, the kernel arbitrarily selects one thread in the process to which to deliver the signal and invokes the handler in that thread. This behavior is cosistent with maintaining the traditional signal semantics. It would not make sense for a process to perform the signal handling actions multiple times in response to a single signal.
To experience the bolded text, I write the following basic code, but when I press Ctrl-C, I get a really different thread id rather than the created ones. Who is this? Why cannot I see that a different thread can catch the signal.
#include <pthread.h>
#include <stdio.h>
#include <signal.h>
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
int count = 0;
int globerr;
void *inc(void *arg) {
fprintf(stderr, "Thread id = %d\n", (int)pthread_self());
sleep(2);
int error;
for (int i = 0; i < 15; ++i) {
if (error = pthread_mutex_lock(&mtx)) {
globerr = error;
return 0;
}
count++;
printf("thread id = %d, count = %d\n", pthread_self(), count);
if (count == 20) {
printf("thread id = %d, SIGNAL count = %d\n", pthread_self(), count);
pthread_cond_signal(&cv);
}
if (error = pthread_mutex_unlock(&mtx)) {
globerr = error;
return 0;
}
}
}
void* watcher(void *arg) {
fprintf(stderr, "Thread id = %d\n", (int)pthread_self());
sleep(2);
int error;
if (error = pthread_mutex_lock(&mtx)) {
globerr = error;
return 0;
}
while (count < 20) {
printf("watcher thread id = %d, BLOCKING count = %d\n", pthread_self(), count);
pthread_cond_wait(&cv, &mtx);
printf("watcher thread id = %d, UNBLOCKING count = %d\n", pthread_self(), count);
}
printf("watcher thread id = %d, count = %d\n", pthread_self(), count);
if (error = pthread_mutex_unlock(&mtx)) {
globerr = error;
return 0;
}
}
static void signal_handler(int sig){
if (sig == SIGINT)
printf("Caught signal for Ctrl+C, Thread id = %d\n", (int)pthread_self());
pthread_cancel(pthread_self());
}
int main(void) {
struct sigaction sigact;
sigact.sa_handler = signal_handler;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = 0;
sigaction(SIGINT, &sigact, (struct sigaction *)NULL);
pthread_t t[3];
for (int i = 0; i < 2; ++i) {
pthread_create(&t[i], 0, inc, 0);
}
pthread_create(&t[2], 0, watcher, 0);
sleep(3);
for (int i = 0; i < 3; ++i) {
pthread_join(t[i], 0);
}
}
Example output,
MacBook-Pro-2:cmake-build-debug soner$ ./client
Thread id = 171921408
Thread id = 172457984
Thread id = 172994560
^CCaught signal for Ctrl+C, Thread id = 360719808
^CCaught signal for Ctrl+C, Thread id = 171921408
^CCaught signal for Ctrl+C, Thread id = 172457984
^CCaught signal for Ctrl+C, Thread id = 172994560
Who is 360719808?