Почему sem_timedwait() не просыпается?
Я работаю на встроенной системе с eCos: у меня есть 2 потока в одном процессе и 1 семафор.
- Поток A инициализирует семафор до 0, поэтому первая попытка его захвата блокируется.
- Поток A отправляет команду в Поток B, обеспечивая обратный вызов.
- Поток А ждет на семафор с
sem_timedwait
- Поток B обрабатывает команду и увеличивает семафор
- Поток А должен быть разбужен, но все еще заблокирован
Вот код:
Нить А
static sem_t semaphore;
void callback()
{
// Do some stuff
int ret = sem_post(&semaphore);
// print confirmation message
}
void foo()
{
int ret = sem_init(&semaphore, 0, 0);
if(ret != 0)
{
// print errno
}
struct timespec ts;
clock_gettime(CLOCK_REALTIME,&ts); // Get current date
ts.tv_sec += 2; // Add 2s for the deadline
send_command_to_thread_B(&callback);
ret = sem_timedwait(&semaphore, &ts);
if(ret != 0)
{
// print errno
}
// print waking up message
}
То, что есть в теме B, не имеет значения.
Для отладки я попробовал следующее:
- С помощью
sem_wait
скорее, чемsem_timedwait
работает: поток А заблокирован, затем разблокирован после обратного вызова. Но я не хочу использовать его, потому что в случае сбоя в процессе обратного вызова, который не позволяет увеличить семафор, поток A будет ждать вечно. - Если я не добавлю 2 к
timespec
структура,sem_timedwait
немедленно возвращается иerrno
установлен вETIMEDOUT
(выглядит вполне законно). Обратный вызов вызывается, но это слишком поздно для потока А. - Я поместил трассировки в вызов обратного вызова, чтобы убедиться, что семафор действительно увеличен с 0 до 1: весь процесс завершен, обратный вызов завершен, но поток A все еще заблокирован.
Ребята, вы понимаете? Я что-то пропустил?
1 ответ
Решение
Итак, на самом деле все в порядке с этим кодом, проблема была в другом месте: у меня была проблема с повторным входом, которая вызвала тупик.
Мораль: тщательно защищайте свои ресурсы и адреса в многопоточном контексте