msgrcv出错errno=4[Interrupted system call]系统调用被信号中断

原创:

今天在嵌入式Linux中调试msgrcv时出现其返回为-1,错误代码4的错误:errno=4[Interruptedsystem call]。错误代码4为: 当进程睡眠等待接收消息时,被信号中断。 这是由于在此线程中同时使用了信号,而慢系统调用(阻塞系统调用)在使线程休眠等待时被信号唤醒,当捕获到某个信号且相应信号处理函数返回时,这个系统调用被中断,调用返回错误,设置errno为EINTR(相应的错误描述为“Interruptedsystem call”)。

网上有人说在安装信号时设置SA_RESTART属性(该方法对有的系统调用无效,在得到了验证),并忽略EINTR错误,我试了无效,最终新开了一个线程,在新的线程里处理msgrcv等msgq的操作,顺利解决了问题。

1.术语

慢系统调用可以被永久阻塞,包括以下几个类别:

2.EINTR介绍

“Interruptedsystem call”)。

系统调用函数

write

由于信号中断,没写成功任何数据。

The call was interrupted by a signal before any data was written.

open

由于信号中断,没读到任何数据。

The call was interrupted by a signal before any data was read.

recv

由于信号中断返回,没有任何数据可用。

The receive was interrupted by delivery of a signal before any data were available.

sem_wait

函数调用被信号处理函数中断。

The call was interrupted by a signal handler.

3.解决类似问题有3种方法

◆人为重启被中断的系统调用

3.1.人为重启被中断的系统调用

-1它的失败是临时性的,如果再次调用则可能成功,这并不是真正的失败,,所以要对这种情况进行处理,典型的方式为:

while((r= read(fd, buf,len))<0&&errno == EINTR);/*do nothing*/

#include poll.hint check_conn_is_ok(socket_t sock) {structpollfd fd;intret = 0;socklen_tlen = 0;fd.fd= sock;fd.events= POLLOUT;while( poll (&fd, 1, -1) == -1 ) {if(errno != EINTR ){perror("poll");return-1;}}len= sizeof(ret);if( getsockopt (sock, SOL_SOCKET, SO_ERROR,&ret,&len) == -1 ) {perror("getsockopt");return-1;}if(ret!= 0) {fprintf(stderr, "socket %d connect failed: %s\n",sock, strerror (ret));return-1;}return0;}在调用connect时,这样使用:#include erron.h….if(connnect()) { if(errno == EINTR) {if(check_conn_is_ok() < 0) {perror();return -1;}else {printf("connect issuccess!\n");} } else {perror("connect");return -1; }}3.2.设置SA_RESTART属性

我们还可以从信号的角度来解决这个问题, 安装信号的时候, 设置 SA_RESTART属性,那么当信号处理函数返回后, 不会让系统调用返回失败,而是让被该信号中断的系统调用将自动恢复。

1. struct sigaction action; 2. action.sa_handler = handler_func; 3. sigemptyset(&action.sa_mask); 4. action.sa_flags = 0; 5. /* 设置SA_RESTART属性 */ 6. action.sa_flags |= SA_RESTART; 7. sigaction(SIGALRM, &action, NULL);

和man msgrcv中就有提到这点:

msgsnd and msgrcv are never automatically restarted after being interrupted by a signal handler, regardless of the setting of the SA_RESTART flag when establishing a signal handler.

3.3.忽略信号

当然最简单的方法是忽略信号,在安装信号时,明确告诉系统不会产生该信号的中断。

struct sigaction action; action.sa_handler = SIG_IGN;sigemptyset(&action.sa_mask);sigaction(SIGALRM, &action, NULL);总结

处理方法有以下三种:①人为重启被中断的系统调用;②安装信号时设置 SA_RESTART属性;③忽略信号(让系统不产生信号中断)。

参考:

转载请注明:

诚实是人生绝妙的法宝。虽然对人诚实,

msgrcv出错errno=4[Interrupted system call]系统调用被信号中断

相关文章:

你感兴趣的文章:

标签云: