ВВЕДЕНИЕ
Прежде всего каждый поток имеет свою собственную маску, которая определяет, какие сигналы он слушает.Когда создается поток, он наследует маску потока, который его создает (позвольте мне назвать его родительский поток) , который активен при вызове pthread_create
.
Как правило, лучше, если поток прослушивает сигнал, а другой - нет, если только вы не хотите иметь много потоков, выполняющих одинаковые действия (например, при обработке запроса на соединение на сервере для обработки).много запросов одновременно).Таким образом, вы всегда знаете, какой поток обрабатывает сигнал.В противном случае вы не знаете, какой поток получает сигнал, а какая часть программы выполняется: отладка становится невозможной (пример - ваш собственный вопрос).
На изменить маску дочернего потока , который создается из родительского потока вы создаете новую маску, вы устанавливаете ее активнойсоздайте новый поток с pthread_create
, а затем в родительском потоке снова установите активную предыдущую маску (см. код в конце ответа).
EDIT : Согласно этой записи лучше использовать sigaction()
вместо signal
.В современных системах signal()
реализован с sigaction()
, поэтому не должно быть никакой разницы.Однако, если используется его старая реализация, могут возникнуть проблемы.
ОТВЕТ
Таким образом, сигнализировать только поток прерываний вместо всего процесса, если есть многопоточность?
NO : Сигналы - это просто сигналы, они ничего не делают.Действия, связанные с сигналами, способны выполнять какие-либо действия, включая остановку программы или завершение потока.С каждым сигналом связано действие по умолчанию, и действие по умолчанию для SIGINT
состоит в прерывании процесса.
С помощью вашего обработчика вы перезаписываете действие по умолчанию.Поэтому он больше не будет останавливать программу, но будет делать то, что вы указали в функции потока.
В первом случае у вас есть только один поток, основной, который является бесконечным циклом, он всегда перехватываетсигнал пока он жив, вот почему и поведение.Если вы повторно отправляете сигнал, он на мгновение блокируется, пока обработчик сигнала не завершит выполнение.Тем не менее, если много сигналов отправлено во время выполнения обработчика, вы можете потерять некоторые сигналы.Фактически, как объяснено здесь , заблокированные сигналы устанавливаются в ожидании, но не ставятся в очередь.Термин pending означает, что операционная система запоминает наличие сигнала, ожидающего доставки при следующей возможности, путем установки флага, а not queue означает, что она делает это, устанавливаяфлаг где-то, но не путем точного учета того, сколько сигналов поступило.Так что, если сигналы отправляются один, 5 или более раз (попробуйте нажать CTRL + C еще раз с вашей программой: я пробовал), пока обработчик сигнала выполняет его, он будет работать точно так же.
В вашемВо втором случае у вас есть 3 потока: main
one, t1
и t2
: все они могут видеть сигнал SIGINT
, и все они связаны с одним обработчиком сигнала.Если вы нажмете 3 раза один за другим, все три из них запустят обработчик: поэтому вы не видите никакой задержки.Если вы нажмете очень очень быстро, хотя и более 3 раз (количество потоков, слушающих этот сигнал), я думаю, вы увидите нечто похожее на первое поведение.
Я закончу свой ответ код, который я разместил в вопросе , где я устанавливал маски так, чтобы некоторые сигналы были перехвачены только основным потоком:
int main()
{
int err;
sigset_t omask, mask;
pthread_t thread_motionSensor;
pthread_t thread_tempReading;
pthread_t thread_platformPost;
printf("Created threads IDs\n");
...
if (signal(SIGINT, sig_handler)==SIG_ERR)
printf("Error on recording SIGINT HANDLER\n");
/*Create a new mask to block all signals for the following thread*/
sigfillset(&mask);
pthread_sigmask(SIG_SETMASK, &mask, &omask);
printf("Trying to create threads\n");
if ((err = pthread_create (&thread_motionSensor, NULL, task1, NULL))!=0)
{
printf("Thread 1 not created: error %d\n", err);
err_exit((const char)err, "pthread_create error");
}
printf("Thread 1 created. Trying to create Thread 2\n");
if((err = pthread_create (&thread_tempReading, NULL, task2, NULL))!=0)
{
printf("Thread 2 not created: error %d\n", err);
err_exit((const char)err, "pthread_create error");
}
printf("Thread 2 created. Trying to create Thread 3\n");
if ((err = pthread_create (&thread_platformPost, NULL, task3, NULL))!=0)
{
printf("Thread 3 not created: error %d %d\n", err);
err_exit((const char)err, "pthread_create error");
}
printf("Thread 3 created\n");
/*The main thread must block the SIGALRM but catch SIGINT
SIGQUIT, SIGTERM, SIgkILL*/
/*empty the omask set from all signals */
sigemptyset(&omask);
/*add the signals to the omask*/
sigaddset(&omask, SIGINT);
sigaddset(&omask, SIGQUIT);
sigaddset(&omask, SIGKILL);
sigaddset(&omask, SIGTERM);
/*unblock all signals in omask*/
pthread_sigmask(SIG_UNBLOCK, &omask, NULL);
printf("Main thread waiting for signal\n");
/*pause will stop the main thread until any signal not blocked by omask will be received*/
pause();
printf("Exit signal received: cancelling threads\n");
pthread_cancel(thread_motionSensor);
pthread_cancel(thread_tempReading);
pthread_cancel(thread_platformPost);
pthread_join(thread_motionSensor, NULL);
pthread_join(thread_tempReading, NULL);
pthread_join(thread_platformPost, NULL);
printf("Exiting from main thread and process\n");
exit(0);
}