Настройка:
Поток A: отправляет сигнал самому себе.
Обработчик сигнала потока A: ожидание pthread_cond
Поток B: отправка сигнала.
Код: Выделить всё
#define _GNU_SOURCE
#include
#include
#include
#include
#include
#include
#include
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
static int flag = 1;
static pthread_t thread_a_tid;
/* -------- Signal handler (INTENTIONALLY BROKEN) -------- */
static void signal_handler(int signo, siginfo_t *info, void *ucontext)
{
int sts;
/* busy-trylock (already illegal in signal handler) */
do {
sts = pthread_mutex_trylock(&mutex);
} while (sts == EBUSY);
while (flag) {
/* Artificial delay to widen race window */
for (volatile unsigned i = 0; i < 100000; ++i) {
__asm__ __volatile__("" ::: "memory");
}
/* ❌ NOT async-signal-safe */
pthread_cond_wait(&cond, &mutex);
}
pthread_mutex_unlock(&mutex);
}
/* -------- Thread A -------- */
static void *thread_a(void *arg)
{
/* Install signal handler */
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_sigaction = signal_handler;
sa.sa_flags = SA_SIGINFO;
sigemptyset(&sa.sa_mask);
if (sigaction(SIGRTMIN + 2, &sa, NULL) != 0) {
perror("sigaction");
exit(1);
}
thread_a_tid = pthread_self();
while (1) {
/* do some job */
usleep(1000);
/* send signal to self */
flag = 1;
pthread_kill(thread_a_tid, SIGRTMIN + 2);
}
return NULL;
}
/* -------- Thread B -------- */
static void *thread_b(void *arg)
{
while (1) {
/* simulate poll() */
usleep(5000);
/* do some job */
/* wake up thread A */
pthread_mutex_lock(&mutex);
flag = 0;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
return NULL;
}
int main(void)
{
pthread_t ta, tb;
if (pthread_create(&ta, NULL, thread_a, NULL) != 0 ||
pthread_create(&tb, NULL, thread_b, NULL) != 0) {
perror("pthread_create");
return 1;
}
pthread_join(ta, NULL);
pthread_join(tb, NULL);
return 0;
}
Вопросы:
Я знаю, что использование pthread_mutex и pthread_cond внутри обработчика сигнала принципиально небезопасно; это не вопрос.
Я пытаюсь понять, может ли это реально объяснить поведение, которое я наблюдаю (например, мьютекс, который работает неправильно, или сигналы, которые кажутся пропущенными), и какой внутренний механизм вызывает такие сбои.
Примечательно, что когда я избегаю обработчика сигналов и выполняю ту же логику непосредственно из потока (что возможно в моем случае), проблема до сих пор не воспроизводится. Я хотел бы понять, является ли это принципиально правильным решением или оно просто маскирует другую основную проблему.
Подробнее здесь: https://stackoverflow.com/questions/798 ... handler-ca
Мобильная версия