connect一定要检查EINTR吗?

yanjinbin0 2010-04-07 10:03:59
我看到一段连接函数,是阻塞的connect但是还是放到一个select中去检查了,不解是因为EINTR中断信号的原因吗?
例如
rtv = connect(sockfd,(struct sockaddr *)&dest_addr, sizeof(struct sockaddr));
if(rtv == 0)
{
return sockfd;
}
if(errno != EINTR) //EINPROGRESS
{
close(sockfd);
return(-1);
}
if(rtv < 0)
{

struct timeval tv;
tv.tv_sec = 10;
tv.tv_usec = 0;

FD_ZERO (&wfd);
FD_ZERO(&rset);
FD_SET(sockfd,&rset);
FD_SET (sockfd, &wfd);
if (select (sockfd + 1,&wfd, NULL, NULL, &tv) == 0)
{
close(sockfd);
return -1;
}

int len = sizeof (error);
if(getsockopt(sockfd,SOL_SOCKET,SO_ERROR,&error,&len) < 0)
{
close(sockfd);
return(-1);
}
return(sockfd);
}
部分代码,不明白 这里是阻塞的connect放到select中能检查??
EINTR错误会中断连接吗???????????
...全文
379 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
kingteng 2010-04-08
  • 打赏
  • 举报
回复
发现之前我说的不大对,对于一个正常阻塞的套接口,如果connect被中断,而且中断的connect调用如果不由内核自动重启的话,那么会返回EINTR,这时候不能再次调用connect等待未完成的连接继续完成,这样作将导致返回EADDRINUSE错误,这种情况下只能调用select来实现
kingpeng1987 2010-04-08
  • 打赏
  • 举报
回复
现在是用循环来处理,出现ENITR错误,就重新启动函数.
对于connect不能重启的函数则需要调用select来等待.
正解
www.zhoin.com
yanjinbin0 2010-04-08
  • 打赏
  • 举报
回复
手写了两个函数,那出来大家有用就收着,简单但有效.
//设置捕获所有信号
void set_catch_signal(void)
{
signal(SIGHUP,catch_signal);
signal(SIGINT,catch_signal);
signal(SIGQUIT,catch_signal);
signal(SIGILL,catch_signal);
signal(SIGABRT,catch_signal);
signal(SIGFPE,catch_signal);
signal(SIGSEGV,catch_signal);
signal(SIGPIPE,catch_signal);
signal(SIGALRM,catch_signal);
signal(SIGTERM,catch_signal);
signal(SIGUSR1,catch_signal);
signal(SIGUSR2,catch_signal);
signal(SIGCHLD,catch_signal);
signal(SIGCONT,catch_signal);
signal(SIGTSTP,catch_signal);
signal(SIGTTIN,catch_signal);
signal(SIGTTOU,catch_signal);
signal(SIGBUS,catch_signal);
signal(SIGPOLL,catch_signal);
signal(SIGPROF,catch_signal);
signal(SIGSYS,catch_signal);
signal(SIGTRAP,catch_signal);
signal(SIGURG,catch_signal);
signal(SIGVTALRM,catch_signal);
signal(SIGXCPU,catch_signal);
signal(SIGXFSZ,catch_signal);
signal(SIGIOT, catch_signal);
// signal(SIGEMT, catch_signal);
signal(SIGSTKFLT, catch_signal);
signal(SIGIO, catch_signal);
signal(SIGCLD, catch_signal);
signal(SIGPWR, catch_signal);
// signal(SIGINFO, catch_signal);
// signal(SIGLOST, catch_signal);
signal(SIGWINCH, catch_signal);
signal(SIGUNUSED, catch_signal);
}

//所有信号都调用该处理函数,打印产生信号值
static void catch_signal(int signo)
{
switch(signo){
case SIGHUP:
{
printf("SIGHUP \n");
break;
}
case SIGINT:
{
printf("SIGINT \n");
break;
}
case SIGQUIT:
{
printf("SIGQUIT \n");
break;
}
case SIGILL:
{
printf("SIGILL \n");
break;
}
case SIGABRT:
{
printf("SIGABRT \n");
break;
}
case SIGFPE:
{
printf("SIGFPE \n");
break;
}
case SIGSEGV:
{
printf("SIGSEGV \n");
break;
}
case SIGPIPE:
{
printf("SIGPIPE \n");
break;
}
case SIGALRM:
{
printf("SIGALRM \n");
break;
}
case SIGTERM:
{
printf("SIGTERM \n");
break;
}
case SIGUSR1:
{
printf("SIGUSR1 \n");
break;
}
case SIGUSR2:
{
printf("SIGUSR2 \n");
break;
}
case SIGCHLD:
{
printf("SIGCHLD \n");
break;
}
case SIGCONT:
{
printf("SIGCONT \n");
break;
}
case SIGTSTP:
{
printf("SIGTSTP \n");
break;
}
case SIGTTIN:
{
printf("SIGTTIN \n");
break;
}
case SIGTTOU:
{
printf("SIGTTOU \n");
break;
}
case SIGBUS:
{
printf("SIGBUS \n");
break;
}
case SIGPOLL:
{
printf("SIGPOLL \n");
break;
}
case SIGPROF:
{
printf("SIGPROF \n");
break;
}
case SIGSYS:
{
printf("SIGSYS \n");
break;
}
case SIGTRAP:
{
printf("SIGTRAP \n");
break;
}
case SIGURG:
{
printf("SIGURG \n");
break;
}

case SIGVTALRM:
{
printf("SIGVTALRM \n");
break;
}
case SIGXCPU:
{
printf("SIGXCPU \n");
break;
}
case SIGXFSZ:
{
printf("SIGXFSZ \n");
break;
}
/*
case SIGIOT:
{
printf("SIGIOT \n");
break;
}

case SIGSTKFLT:
{
printf("SIGSTKFLT \n");
break;
}
case SIGIO:
{
printf("SIGIO \n");
break;
}
case SIGCLD:
{
printf("SIGCLD \n");
break;
}
case SIGPWR:
{
printf("SIGPWR \n");
break;
}
case SIGWINCH:
{
printf("SIGWINCH \n");
break;
}
case SIGUNUSED:
{
printf("SIGUNUSED \n");
break;
}
*/
default:
printf("no signal %d \n",signo);
break;
}
// printf("SIGALRM \n");
return;
}
yanjinbin0 2010-04-08
  • 打赏
  • 举报
回复
现在我想知道是那个信号中断我的connect,如果捕获程序信号,并打印出来。
yanjinbin0 2010-04-07
  • 打赏
  • 举报
回复
有人在开发中遇到这些问题吗?
kingteng 2010-04-07
  • 打赏
  • 举报
回复
用非阻塞的connect的话,如果正好有一个连接已经在队列里,那么connect成功,如果没有的话,也会立即返回,但是返回一个EINPROGRESS错误
yanjinbin0 2010-04-07
  • 打赏
  • 举报
回复
现在是用循环来处理,出现ENITR错误,就重新启动函数.
对于connect不能重启的函数则需要调用select来等待.
kingteng 2010-04-07
  • 打赏
  • 举报
回复
不好意思没有想到什么好方法,我不知道怎么捕获所有信号。。。但是我觉得你可以插入断点,单步调试,可能会给你程序产生的信号。。。可能
yanjinbin0 2010-04-07
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 kingteng 的回复:]
程序在执行的过程中会产生一些不预期的信号,比如硬件的错误导致的SIGBUS等,可能会打断connect的调用,而connect是不可重入的,所以检查一下还是有必要的
[/Quote]

现在就是老被其他信号打断导致我连接不上,但我想知道到底是那个信号打断的,但是不知道怎么去查找,你有什么办法吗??

如果不行,设置connect非阻塞方式是否不会被信号打断.
kingteng 2010-04-07
  • 打赏
  • 举报
回复
程序在执行的过程中会产生一些不预期的信号,比如硬件的错误导致的SIGBUS等,可能会打断connect的调用,而connect是不可重入的,所以检查一下还是有必要的
yanjinbin0 2010-04-07
  • 打赏
  • 举报
回复
能不能忽略这个中断信号啊.
为什么这里连接会跑出个中断信号出来啊 .
atiansk2006 2010-04-07
  • 打赏
  • 举报
回复

rtv = connect(sockfd,(struct sockaddr *)&dest_addr, sizeof(struct sockaddr));
if(rtv == 0)
{
return sockfd;
}
if(errno != EINTR) //EINPROGRESS
{
close(sockfd);
return(-1);
}
if(rtv < 0)
{

struct timeval tv;
tv.tv_sec = 10;
tv.tv_usec = 0;

FD_ZERO (&wfd);
FD_ZERO(&rset);
FD_SET(sockfd,&rset);
FD_SET (sockfd, &wfd);
if (select (sockfd + 1,&wfd, NULL, NULL, &tv) == 0)
{
close(sockfd);
return -1;
}

int len = sizeof (error);
if(getsockopt(sockfd,SOL_SOCKET,SO_ERROR,&error,&len) < 0)
{
close(sockfd);
return(-1);
}
return(sockfd);
}

hittlle 2010-04-07
  • 打赏
  • 举报
回复
检查一下没错儿;APUE上说,一般只检查那些“慢”(slow)的系统调用吧;好像是这么说的,有点忘记了;还有就是中断后不能自动重启的调用,都应该检查是不是被中断了

23,120

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧