问题背景:
源码中在调用getaddrinfo时,如果是网络正常的环境下,getaddrinfo返回会很快,但如果无网络,机器就无法进行dns解析,从而导致getaddrinfo返回时间高达1-2分钟以上。
解决方案:使用多线程执行getaddrinfo
源码如下:
//add by xdl
struct stu_dns_info
{
LPCSTR node;
LPCSTR servname;
struct addrinfo *hints;
struct addrinfo **res;
pthread_t pid;
};
void *thread_get_addr_info(void *arg)
{
pthread_detach(pthread_self());
int ret = 0;
struct stu_dns_info *s_dns_info = (struct stu_dns_info *)arg;
char *node = NULL;
char* servname = NULL;
if(s_dns_info->node != NULL)
{
node = strdup(s_dns_info->node);
}
if(s_dns_info->servname !=NULL)
{
servname = strdup(s_dns_info->servname);
}
struct addrinfo hints;
hints.ai_socktype = s_dns_info->hints->ai_socktype;
hints.ai_protocol = s_dns_info->hints->ai_protocol;
hints.ai_flags = s_dns_info->hints->ai_flags;
struct addrinfo* res = NULL;
pthread_t pid_master = s_dns_info->pid;
ret = getaddrinfo(node, servname, &hints, &res);
FIXME("xdl result = %d\n", ret);
if(ret != 0)
{
goto out;
}
ret = pthread_kill(pid_master, 0);
if(0 == ret)
{
if(s_dns_info->res == NULL)
{
freeaddrinfo(res);
goto out;
}
*(s_dns_info->res) = res;
}
else
{
freeaddrinfo(res);
}
out:
if (node != NULL)
free(node);
if (servname != NULL)
free(servname);
pthread_exit(NULL);
}
int WINAPI my_getaddrinfo(LPCSTR node, LPCSTR servname, struct addrinfo *punixhints, struct addrinfo **unixaires)
{
pthread_t t1 = 0;
int ret = 0;
int count = 0;
struct stu_dns_info s_dns_info;
s_dns_info.node = node;
s_dns_info.servname = servname;
s_dns_info.hints = punixhints;
s_dns_info.res = unixaires;
s_dns_info.pid = pthread_self();
ret = pthread_create(&t1, NULL, thread_get_addr_info, (void *)&s_dns_info);
if(ret == -1)
{
FIXME("pthread_create error\n");
return -1;
}
//int result = getaddrinfo(node, servname, punixhints, unixaires);
int btimeout = 1;
for(count = 0; count < 20; ++count)
{
ret = pthread_kill(t1, 0);
if(0 == ret)
{
FIXME("thread exist\n");
usleep(100*1000);//100ms
}
else if(ESRCH == ret)
{
FIXME("thread not exist\n");
btimeout = 0;
break;
}
}
if( 0 == btimeout && NULL != *(s_dns_info.res))
{
ret = 0;
}
else
{
ret = -1;
}
return ret;
}
//end
主线程中每100ms循环一次,通过pthread_kill检测子线程是否还存在,超时时间2s,同样,子线程也会去检测主线程是否还在,子线程中结构体数据使用strdup进行了保存,防止主线程退出后,传进来的指针数据丢失。