sem_wait()
.Функция
sem_wait()
уменьшает текущее значение семафора на 1. Если прежнее значение семафора было 0, то поток, выполняющий функцию sem_wait
, блокируется до изменения значения семафора. При успешном выполнении — функция возвращает 0; при ошибке — вернет -1, а errno
будет содержать код ошибки.Вот пример неправильной обработки возвращаемого значения:
int res = sem_wait(&sem);
if (0 != res)
{
// Ошибка!
// Сообщаем об ошибке и выходим.
...
return;
}
// Ошибки нет - продолжаем работу.
...
Что здесь неправильно? Дело в том, что функция
sem_wait()
является блокирующим системным вызовом. Поэтому выполнение этой функции может быть прервано, если выполняющийся поток получит какой-нибудь сигнал (например, сигнал о завершении другого потока). В этом случае функция вернет -1, а errno
будет равна EINTR
.При этом никакой ошибки на самом деле нет, это просто способ дать программе обработать пришедший сигнал. Это необходимо учитывать, и вызов
sem_wait()
лучше всего делать в цикле. Например, таком:
int res;
do
{
res = sem_wait(&sem);
}
while (0 != res && EINTR == errno);
if (0 != res)
{
// Ошибка!
// Сообщаем об ошибке и выходим.
...
return;
}
// Ошибки нет - продолжаем работу.
...
Это касается и других блокирующих функций. Например,
select
, wait
, waitpid
и др. Возможность прерывания функции с ошибкой EINTR
обычно описана в man'е.