Создать обработчик сигнала для одного потока
Мне интересно, если sigaction
создаст обработчик сигнала для вызывающего потока или всего процесса. Если он разблокирует сигнал и создаст обработчик сигнала для всего процесса, то как я могу убедиться, что только один поток будет использовать обработчик сигнала и другие потоки будут блокировать сигнал?
В моем случае я хочу, чтобы один поток вызывал обработчик сигнала, когда срабатывает сигнал тревоги, а другие потоки просто блокируют его.
void alarmSigHandler(int signo){
}
void* alarm_thread_start_routine(void *arg){
// Perform some tasks
}
int main(){
// Main thread start
/* Unblock alarm signal */
/* Assign signal handler for alarm signal */
/* Launch alarm signal handler thread */
/* Block alarm signal with pthread_sigmask */
/* Do something */
return 0;
}
http://vip.cs.utsa.edu/classes/cs3733f2013/notes/SignalsAndThreads.html
Если сигнал передается в многопоточную программу, любой из потоков может обработать сигнал.
Каждый поток наследует маску сигналов процесса, но каждый поток имеет свою собственную маску сигналов, которую можно изменить с помощью pthread_sigmask.
sigprocmask не следует использовать в многопоточной среде, но его можно использовать до создания потоков.
Самый простой способ обработки сигналов в многопоточной среде - это создать поток, предназначенный для обработки сигналов.
Проблемы, связанные с безопасностью сигнала, могут быть решены с помощью sigwait:
The main process blocks all signals before creating any threads.
No signal handlers are set up.
A thread is created to handle the signals.
That thread sets up a sigset_t containing the signals of interest.
It loops, calling sigwait and handles the pending signals.
2 ответа
Со страницы руководства для сигналов:
Расположение сигнала является атрибутом процесса: в многопоточном приложении расположение конкретного сигнала одинаково для всех потоков.
Так что да, когда вы устанавливаете обработчик сигналов, он будет обрабатывать сигналы, отправленные процессу; сигналы не отправляются каждому потоку в отдельности, он отправляется любому из потоков, которые не блокируют конкретное отправляемое сообщение.
Ты говоришь:
В моем случае я хочу, чтобы один поток вызывал обработчик сигнала, когда срабатывает сигнал тревоги, а другие потоки просто блокируют его.
Попробуй это:
void *alrm_thread(void *arg) {
// install SIGALRM handler
// unblock SIGALRM
... do stuff ...
}
int main(int argc, char **argv) {
// block SIGALRM
// spawn alarm_thread
... do stuff or spawn other threads ..
}
SIGALRM будет доставлен только к "alrm_thread" выше.
ОБНОВИТЬ
(Адаптируя меткие комментарии Alex Che)
Это работает, потому что каждый поток имеет свою собственную маску сигналов, унаследованную от потока, который ее создает.
Маскировка (блокировка) СИГАЛРМ в main()
сразу же гарантирует, что все последующие потоки начнут жизнь с заблокированным SIGALRM. Наш специальный поток устанавливает обработчик и разблокирует SIGALRM. Поскольку этот специальный поток является единственным потоком, способным получить ALRM, он будет потоком, который запускает обработчик.
(Теперь есть некоторые нюансы сигнала прямо за углом. Обработчики или расположение сигналов являются глобальными атрибутами процесса, общими для всех потоков. Сигналы могут быть ориентированы на процесс или на поток. Однако для вашего случая, который является очень распространенным случаем Вышесказанное подходит.)