From APUE:
To prevent applications from having to handle interrupted system calls, 4.2BSD introduced the automatic restarting of certain interrupted system calls. The system calls that were automatically restarted are
ioctl,read,readv,write,writev,wait, andwaitpid. As we’ve mentioned, the first five of these functions are interrupted by a signal only if they are operating on a slow device;waitandwaitpidare always interrupted when a signal is caught. Since this caused a problem for some applications that didn’t want the operation restarted if it was interrupted, 4.3BSD allowed the process to disable this feature on a per-signal basis.
Does it mean that before automatic restarting was introduced, if a process catch a signal, wait and waitpid would immediately stop waiting and execute the subsequent code?
For example:
#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;
}
If not providing automatic restarting, when I run this program in the background gcc test.c && ./a.out &, then I send a signal kill -SIGUSR1 pid or kill -SIGUSR2 pid, waitpid would return and the code after waitpid(pid, &status, 0); would execute.
And if providing automatic restarting, waitpid would execute again and the parent will remain waiting.
Is my understanding correct?
The original behaviour of signal() (System-V semantics) was, to interrupt any system call if the process currently slept, execute the signal handler and the system call returns with -EINTR. Then, BSD4.3 invented the restart mechanism, which would restart any system call automatically after it was interrupted. This avoids having to write a loop for each syscall if signal handlers are involved.
Linux did not change the semantics of the signal() syscall. However, the signal() glibc wrapper function nowadays calls the syscall sigaction() with SA_RESTART flag by default. So, if you do not need the restart behaviour, you have to call sigaction() and omit that flag.
So, your code indeed makes use of the restart mechanism on both BSD and linux
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With