С man -e 2 wait
:
Ожидание вызова (& статус) эквивалентно:
waitpid (-1, & status, 0);
ошибочные значения:
EINTR WNOHANG не был установлен, и был разблокирован сигнал или SIGCHLD
поймали; см. сигнал (7).
Так что, исходя из моего понимания выше, если мы заблокированы в «ожидании» и получении сигнала (SIGCHLD), вызов должен вернуться с -1 и для errno установлено значение EINTR.
Хотя запуск следующего фрагмента докажет, что ожидание фактически перезапущено (linux 4.15.0-43, glibc 2.23):
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
static void sigchld_handler(int signo)
{
const char *const msg = "\nSIGCHLD";
(void)signo;
write(STDERR_FILENO, msg, strlen(msg));
}
int main(void)
{
pid_t wait_ret = 0, pid = 0;
int status = 0, ret = -1;
sigaction(SIGCHLD, &(struct sigaction){
.sa_handler = sigchld_handler,
}, NULL);
if ((pid = fork()) < 0)
{
perror("\nfork: ");
goto Exit;
}
if (!pid)
{
sleep(3);
return 0;
}
if ((wait_ret = wait(&status)) < 0)
{
perror("\nwait: ");
goto Exit;
}
fprintf(stderr, "\nwait done, pid %d", wait_ret);
ret = 0;
Exit:
fprintf(stderr, "\n");
return ret;
}
SA_RESTART не установлен - так почему перезапуск "wait".?
Фактический объем производства:
SIGCHLD
wait done, pid 15242
Ожидаемый мной вывод:
SIGCHLD
wait: Interrupted system call
Примечание kill -CHLD <waiting process>
вручную из оболочки даст ожидаемый результат.
Также обратите внимание, что выполнение кода во FreeBSD 11.2 также даст ожидаемый результат - ожидание прерывается с ошибкой при выходе из дочернего процесса.