I am trying to learn signal processing between processes and threads. Answering a few questions will help me better understand this.
I know that a process can send a signal to a group of processes and allow several processes to receive the same signal, but I'm not sure about the threads.
- Can signals sent to all pthreads be processed simultaneously by more than one pthread?
I configure my program to block all signals using pthread_sigmask() , I have two threads: sigwait(SIGUSR1) wait for signals, and I have a main thread sending signals SIGUSR1. Everything seems to work well when only one thread processes the signals (I comment on the code in the other), but when both run the sigwait() code, it hangs or ends too quickly.
The code will be inserted below.
sig_atomic_t signals = 0; sig_atomic_t sigusr1_signals = 0; sig_atomic_t sigusr2_signals = 0; sig_atomic_t count = 0; sig_atomic_t totalcount = 0; sigset_t globalset; int WAIT = 1; /* false = 0, true = 1 */ static int SIGNALS_SENT = 0; static int SIGNALS_RECEIVED = 0; void *sig1handler1(void *argv); void *reporterhandler(void *argv); int random_number(int min, int max); int main(void) { pthread_t threads[2]; /* create an array to store a number of threads */ //int *p_status = &status; sigfillset(&globalset); pthread_sigmask(SIG_BLOCK, &globalset, NULL); /* Generate signal handling threads */ if (pthread_create(&threads[0], NULL, &sig1handler1, NULL) > 0) { printf("Thread creation failure!\n"); return -1; } /* create reporting thread */ if (pthread_create(&threads[1], NULL, &reporterhandler, NULL) > 0) { printf("Thread creation failure!\n"); return -1; } /* Signal all threads to begin work concurrently */ WAIT = 0; int c = 0; while(c < 100) { int value = random_number(1, 2); if (value == 1) kill(0, SIGUSR1); else kill(0, SIGUSR2); SIGNALS_SENT++; c++; usleep(10000); } kill(0, SIGINT); /* Wait for each thread to finish and join */ int i = 0; for(i = 0; i < 2; i++) { if (pthread_join(threads[i], NULL) > 0) { printf("Thread [%u] join failure!\n", (unsigned int)threads[i]); return -1; } printf("THREAD [%u] returned.\n", (unsigned int)threads[i]); } printf("Parent Process [%d] exiting successfully.\n", getpid()); return EXIT_SUCCESS; } void *sig1handler1(void *argv) { pthread_t tid = pthread_self(); printf("THREAD[%u] sig1handler1: waiting for signal to do some work...\n", (unsigned int)tid); // sigset_t myset; // sigfillset(&myset); // sigdelset(&myset, SIGINT); // sigdelset(&myset, SIGUSR1); // pthread_sigmask(SIG_SETMASK, &myset, NULL); /* Wait for a signal to start work */ while (WAIT); int sig; int count = 0; while(1) { sigwait(&globalset, &sig); if (sig == SIGUSR1) { sigusr1_signals++; signals++; count++; //printf("thread1: caught SIGUSR1 signal!\n"); } else if (sig == SIGINT) { printf("thread1: caught SIGINT signal, detected SIGUSR1 %d times, and terminating!\n", count); pthread_exit(NULL); } } //printf("THREAD[%u] sig1handler1: doing some work!\n", (unsigned int)tid); //return (void *)EXIT_SUCCESS; //return (void *)NULL; pthread_exit(NULL); } void *reporterhandler(void *argv) { pthread_t tid = pthread_self(); printf("THREAD[%u] reporter: waiting for signal to do some work...\n", (unsigned int)tid); int sig; int count = 0; // sigset_t myset; // sigfillset(&myset); // sigdelset(&myset, SIGINT); // sigdelset(&myset, SIGUSR1); // sigdelset(&myset, SIGUSR2); // pthread_sigmask(SIG_SETMASK, &myset, NULL); /* Wait for a signal to start work */ while (WAIT); while(1) { sigwait(&globalset, &sig); if (sig == SIGUSR1) { sigusr1_signals++; signals++; count++; totalcount++; SIGNALS_RECEIVED++; } else if (sig == SIGUSR2) { sigusr2_signals++; signals++; count++; totalcount++; SIGNALS_RECEIVED++; } else if (sig == SIGINT) { printf("Reporter: SIGUSR1 detected %d times\n", sigusr1_signals); printf("Reporter: SIGUSR2 detected %d times\n", sigusr2_signals); printf("Reporter: detected %d signals\n", totalcount); printf("Reporter: SIGNALS_SENT %d \n", SIGNALS_SENT); printf("Reporter: SIGNALS_REC %d \n", SIGNALS_RECEIVED); pthread_exit(NULL); } /* Display Report after detecting 10 signals */ if (count == 10) sigusr1_signals, sigusr2_signals); count = 0; } } //printf("THREAD[%u] reporter: doing some work!\n", (unsigned int)tid); pthread_exit(NULL); } int random_number(int min, int max) { if (min < max) { max = max + 1; /* include the max value */ return (rand() % (max - min)) + min; } return -1; }