От APUE:
Чтобы приложениям не приходилось обрабатывать прерванные системные вызовы, в 4.2BSD введен автоматический перезапуск некоторых прерванных системных вызовов. Автоматически перезапускаются следующие системные вызовы:
ioctl
,read
,readv
,write
,writev
,wait
, иwaitpid
. Как мы уже упоминали, первые пять из этих функций прерываются по сигналу только в том случае, если они работают на медленном устройстве;wait
иwaitpid
всегда прерываются при перехвате сигнала. Поскольку это вызывало проблему для некоторых приложений, которые не хотели перезапускать операцию, если она была прервана, 4.3BSD позволяла процессу отключать эту функцию при основе для каждого сигнала.
Означает ли это, что до введения автоматического перезапуска, если процесс ловил сигнал, wait
и waitpid
немедленно прекращали ожидание и выполняли последующий код?
Например:
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
void handler(int sig){}
void handler2(int sig){}
int main(){
pid_t pid;
int status;
signal(SIGUSR1, handler);
signal(SIGUSR2, handler2);
if((pid == fork()) < 0){
printf("fork error\n");
}else{
if(pid){
//child
//do something, needs several hours.
}else{
//parent
waitpid(pid, &status, 0);
printf("Hello world\n");
}
}
return 0;
}
Если не обеспечить автоматический перезапуск, когда я запускаю эту программу в фоновом режиме gcc test.c && ./a.out &
, то я посылаю сигнал kill -SIGUSR1 pid
или kill -SIGUSR2 pid
, waitpid
возвращается и выполняется код после waitpid(pid, &status, 0);
.
А если обеспечить автоматический перезапуск, waitpid
будет выполняться снова, а родительский элемент останется в ожидании.
Правильно ли я понимаю?
errno
вEINTR
. Что бы ни случилось дальше, зависит от того, как вызывающая сторона обрабатывает этот случай. Если он перезапускается, он не вернется с этим конкретным кодом ошибки, если иное не задокументировано для этого. Это будет продолжаться до тех пор, пока не вернется по какой-то другой причине. - person Shawn   schedule 29.03.2019sigaction()
, а неsignal()
, чтобы получить контроль над этим, аsigaction()
предоставляет флаг управленияSA_RESTART
, чтобы указать, следует ли возобновлять системные вызовы после обработки сигнала. - person Jonathan Leffler   schedule 29.03.2019signal()
по умолчанию действительно применяет поведение перезапуска в настоящее время в Linux и bsd (по крайней мере) - person Ctx   schedule 29.03.2019