我需要在超时后中断系统调用(在本例中为recvfrom
)。为此,我使用alarm()
,但是产生的SIGALRM会杀死我的进程,而不仅仅是中断系统调用。
我已经尝试调用signal(SIGALRM, SIG_IGN)
来处理SIGALRM,但这会导致系统调用根本不会中断!我让这个工作的唯一方法是创建一个自定义的空处理程序(signal(SIGALRM, alrm_handler)
) -处理程序不做任何事情,但它仍然导致recvfrom
被中断而不杀死进程。
我理解默认的信号处理程序(SIG_DFL)将杀死进程,但我希望SIG_IGN忽略信号,但仍然中断系统调用。如果strace
使用SIG_IGN和自定义空处理程序创建一个测试程序,它们最终都调用了没有SA_RESTART的rt_sigaction(SIGALRM...)
。据我所知,如果SA_RESTART 设置了,那么系统调用将自动重新启动,但无论如何SIG_IGN都会发生这种情况!
有没有更干净的方法来中断系统调用与SIGALRM而不需要自定义信号处理程序?
当您告诉操作系统忽略一个信号时,如果它收到信号后什么也不做而忽略它,您不应该感到惊讶。POSIX只允许recvfrom
在中断时返回EINTR,并且只有在调用信号处理程序时才会中断。当SIG_IGN
设置为POSIX时,要求"信号的传递不会对进程产生影响"。
在套接字操作上设置超时的更好方法是使用setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, ...)
在套接字上设置超时。如果超时,您将得到EAGAIN
或EWOULDBLOCK
错误。
您可能还想看看select
,它可以潜在地消除使用超时的需要。