Linux下关于curl卡死的情况分析
来源:互联网 发布:腾讯软件管家 编辑:程序博客网 时间:2024/05/01 08:13
最近在Linux嵌入式平台上使用curl出现卡死的情况。
1.第一种情况
在发送的时候不加上链接超时和发送超时,这样子很容易造成在发送的时候出现卡死的现象,导致线程阻塞
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
2.第二种情况是加上链接超时和发送超时
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
这种情况,在发送的时候不会出现卡死的状况,但是如果在发送的时候,设备的断网后,再链接网以后,会出现程序崩溃的现象
3.第三种情况加上
既然第二种情况会出现崩溃,我们加上
//Setting CURLOPT_NOSIGNAL to 1 makes libcurl NOT ask the system to ignore SIGPIPE signals
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1)
为什么加上这个呢,先看下下面这段代码:
int Curl_resolv_timeout(struct connectdata *conn, const char *hostname, int port, struct Curl_dns_entry **entry, time_t timeoutms){#ifdef USE_ALARM_TIMEOUT#ifdef HAVE_SIGACTION struct sigaction keep_sigact; /* store the old struct here */ volatile bool keep_copysig = FALSE; /* wether old sigact has been saved */ struct sigaction sigact;#else#ifdef HAVE_SIGNAL void (*keep_sigact)(int); /* store the old handler here */#endif /* HAVE_SIGNAL */#endif /* HAVE_SIGACTION */ volatile long timeout; volatile unsigned int prev_alarm = 0; struct Curl_easy *data = conn->data;#endif /* USE_ALARM_TIMEOUT */ int rc; *entry = NULL; if(timeoutms < 0) /* got an already expired timeout */ return CURLRESOLV_TIMEDOUT;#ifdef USE_ALARM_TIMEOUT if(data->set.no_signal)// 注意 /* Ignore the timeout when signals are disabled */ timeout = 0; else timeout = timeoutms; if(!timeout) /* USE_ALARM_TIMEOUT defined, but no timeout actually requested */ return Curl_resolv(conn, hostname, port, entry); if(timeout < 1000) { /* The alarm() function only provides integer second resolution, so if we want to wait less than one second we must bail out already now. */ failf(data, "remaining timeout of %ld too small to resolve via SIGALRM method", timeout); return CURLRESOLV_TIMEDOUT; } /* This allows us to time-out from the name resolver, as the timeout will generate a signal and we will siglongjmp() from that here. This technique has problems (see alarmfunc). This should be the last thing we do before calling Curl_resolv(), as otherwise we'd have to worry about variables that get modified before we invoke Curl_resolv() (and thus use "volatile"). */ if(sigsetjmp(curl_jmpenv, 1)) { /* this is coming from a siglongjmp() after an alarm signal */ failf(data, "name lookup timed out"); rc = CURLRESOLV_ERROR; goto clean_up; } else { /************************************************************* * Set signal handler to catch SIGALRM * Store the old value to be able to set it back later! *************************************************************/#ifdef HAVE_SIGACTION sigaction(SIGALRM, NULL, &sigact); keep_sigact = sigact; keep_copysig = TRUE; /* yes, we have a copy */ sigact.sa_handler = alarmfunc;#ifdef SA_RESTART /* HPUX doesn't have SA_RESTART but defaults to that behaviour! */ sigact.sa_flags &= ~SA_RESTART;#endif /* now set the new struct */ sigaction(SIGALRM, &sigact, NULL);#else /* HAVE_SIGACTION */ /* no sigaction(), revert to the much lamer signal() */#ifdef HAVE_SIGNAL keep_sigact = signal(SIGALRM, alarmfunc);#endif#endif /* HAVE_SIGACTION */ /* alarm() makes a signal get sent when the timeout fires off, and that will abort system calls */ prev_alarm = alarm(curlx_sltoui(timeout/1000L)); }#else#ifndef CURLRES_ASYNCH if(timeoutms) infof(conn->data, "timeout on name lookup is not supported\n");#else (void)timeoutms; /* timeoutms not used with an async resolver */#endif#endif /* USE_ALARM_TIMEOUT */ /* Perform the actual name resolution. This might be interrupted by an * alarm if it takes too long. */ rc = Curl_resolv(conn, hostname, port, entry);#ifdef USE_ALARM_TIMEOUTclean_up: if(!prev_alarm) /* deactivate a possibly active alarm before uninstalling the handler */ alarm(0);#ifdef HAVE_SIGACTION if(keep_copysig) { /* we got a struct as it looked before, now put that one back nice and clean */ sigaction(SIGALRM, &keep_sigact, NULL); /* put it back */ }#else#ifdef HAVE_SIGNAL /* restore the previous SIGALRM handler */ signal(SIGALRM, keep_sigact);#endif#endif /* HAVE_SIGACTION */ /* switch back the alarm() to either zero or to what it was before minus the time we spent until now! */ if(prev_alarm) { /* there was an alarm() set before us, now put it back */ unsigned long elapsed_ms = Curl_tvdiff(Curl_tvnow(), conn->created); /* the alarm period is counted in even number of seconds */ unsigned long alarm_set = prev_alarm - elapsed_ms/1000; if(!alarm_set || ((alarm_set >= 0x80000000) && (prev_alarm < 0x80000000)) ) { /* if the alarm time-left reached zero or turned "negative" (counted with unsigned values), we should fire off a SIGALRM here, but we won't, and zero would be to switch it off so we never set it to less than 1! */ alarm(1); rc = CURLRESOLV_TIMEDOUT; failf(data, "Previous alarm fired off!"); } else alarm((unsigned int)alarm_set); }#endif /* USE_ALARM_TIMEOUT */ return rc;}
/* The alarm() function only provides integer second resolution, so if
we want to wait less than one second we must bail out already now. */
failf(data,
"remaining timeout of %ld too small to resolve via SIGALRM method",
timeout);
return CURLRESOLV_TIMEDOUT;
}
4.第四钟情况
第四种情况是,curl能在超时的时候正常返回,但是还是会出现curl卡死的情况
那是因为curl正常是只用系统的DNS进行解析,那就是DNS解析将不受超时限制了, 万一DNS服务器 卡住了话, 那就可能会造成curl卡死的情况。
那么使用了curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1)还是有问题,无奈之下,只能libcurl使用c-ares(C library for asynchronous DNS requests)来做名字解析,编编译curl的时候加上编译选项./configure --enable-ares这样子就可以不使用curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1)了。
- Linux下关于curl卡死的情况分析
- Linux下关于解决JavaSwing中文乱码的情况
- Linux下关于解决JavaSwing中文乱码的情况
- Linux下关于解决JavaSwing中文乱码的情况
- JQuery下关于$.Ready()的分析
- Linux下关于内存的查看
- Linux下关于网络设置的文件
- Linux下关于热插拔硬盘的指令
- Linux下关于热插拔硬盘的指令
- Linux下关于NFS的配置步骤
- Linux下关于环境变量的一些心得
- Linux下关于环境变量的一些心得
- linux下关于tomcat的几个问题
- linux下关于tomcat的几个问题
- linux c 下关于semaphore的使用
- linux下关于CPU使用率的代码
- Linux下关于环境变量的一些心得
- Linux 下关于网络的几个命令
- c++实验4:输出星号图
- Java创建WebService服务及客户端实现
- iMX6 音频编解码器 SGTL5000 扩展
- 2017.04.19:今日头条数据分析笔试01
- js判断手机端还是PC端
- Linux下关于curl卡死的情况分析
- Eureka、Ribbon和Feign
- SYD8801定时器使用说明
- ST算法 rmq 模板
- MYSQL workbench使用
- Spring Cache抽象详解
- Spring-Boot自定义启动图案
- 使用httpclient传递java参数调用http接口
- C++第4次实验—循环结构程序设计