用于 Linux 列表的signal(7)
accept
connect
fcntl
flock
futex
ioctl
open
read
readv
recv
recvfrom
recvmsg
send
sendmsg
sendto
wait
wait3
wait4
waitid
waitpid
write
writev
可能被 no-SA_RESTART 处理程序中断 (EINTR) 和
setsockopt
accept
recv
recvfrom
recvmsg
connect
send
sendto
sendmsg
pause
sigsuspend
sigtimedwait
sigwaitinfo
epoll_wait
epoll_pwait
poll
ppoll
select
lect
msgrcv
msgsnd
semop
semtimedop
clock_nanosleep
nanosleep
read
io_getevents
sleep
作为 EINTR 可中断的,即使是 SA_RESTART 处理程序。
此外,它还列出:
setsockopt
accept
recv
recvfrom
recvmsg
connect
send
sendto
sendmsg
epoll_wait
epoll_pwait
semop
semtimedop
sigtimedwait
sigwaitinfo
read
futex
msgrcv
msgsnd
nanosleep
作为 EINTR 可被停止信号 + 中断SIGCONT
,并表示此特定行为是 Linux 特定的,不受POSIX.1
.
除此之外,特别是如果函数的规范没有列出EINTR
,你不应该得到EINTR
.
如果您不相信系统会尊重它,您可以尝试使用带有无操作处理程序的SIGSTOP
/ SIGCONT
+ 信号用您怀疑的系统功能轰炸循环,no-SA_RESTART
看看您是否可以引出 EINTR。
我试过了:
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
static void chld(int Sig)
{
int status;
if(0>wait(&status))
_exit(1);
if(!WIFEXITED(status)){
//this can only interrupt an AS-safe block
assert(WIFSIGNALED(status) && WTERMSIG(status) == SIGALRM);
puts("OK");
exit(0);
} else {
switch(WEXITSTATUS(status)){
case 1: puts("FAIL"); break;
case 2: puts("EINTR"); break;
}
}
exit(0);
}
static void nop(int Sig)
{
}
int main()
{
sigset_t full;
sigfillset(&full);
sigaction(SIGCHLD, &(struct sigaction){ .sa_handler=chld, .sa_mask=full, .sa_flags=0 } , 0);
sigaction(SIGUSR1, &(struct sigaction){ .sa_handler=nop, .sa_mask=full, .sa_flags=0 } , 0);
pid_t p;
if(0>(p=fork())) { perror(0); return 1; }
if(p!=0){
//bombard it with SIGSTOP/SIGCONT/SIGUSR1
for(;;){
usleep(1); kill(p, SIGSTOP); kill(p, SIGCONT); kill(p, SIGUSR1);
}
}else{
sigaction(SIGCHLD, &(struct sigaction){ .sa_handler=SIG_DFL }, 0);
if(0>alarm(1))
return 1;
for(;;){
#if 1
/*not interruptible*/
if(0>access("/dev/null", R_OK)){
if(errno==EINTR)
return 2;
perror(0);
return 1;
}
#else
int fd;
unlink("fifo");
if(0>mkfifo("fifo",0600))
return 1;
/*interruptible*/
if(0>(fd=open("fifo", O_RDONLY|O_CREAT, 0600))){
if(errno==EINTR)
return 2;
perror(0);
return 1;
}
close(fd);
#endif
}
}
return 0;
}
并且绝对看起来是 EINTR 不间断unlink
的access
(符合他们的规范),这意味着EINTR
围绕它们的 -retry 循环将是不必要的。