curl 多线程在android下无故退出的问题

在android下无故退出,使用DS-5调试发现是signal 14造成造成的。

补充OpenSSL锁定问题也可能导致crash.

参见下面的链接

http://blog.youkuaiyun.com/jaylong35/article/details/6988690

引用

==========================================================

1. In multi-threaded application, be careful never to share a curl session handle between multiple threads simultaneously.

2. Use CURLOPT_NOSIGNAL in multi-threaded application to prevent SIGALARM to be triggered in case of curl timeout. The curl_easy_perform() will return instead of being interrupted by SIGALARM. The pitfall is that there is no effective way to time out a slow name resolver in case of using synchronous name resolver.

3. Some well documented in the libcurl documentation. Start by reading
http://curl.haxx.se/libcurl/c/libcurl-tutorial.html then move on to
http://curl.haxx.se/libcurl/c/libcurl-errors.html,
http://curl.haxx.se/libcurl/c/curl_easy_setopt.html and
http://curl.haxx.se/libcurl/c/curl_easy_perform.html for the specifics.


4. Some posts talking about libcurl segmentation fault in multi-thread application due to name resolve timeout and signal      

 

http://curl.haxx.se/mail/lib-2011-02/0275.html


http://www.mail-archive.com/curl-library@cool.haxx.se/msg07629.html

引用

========================================================================

1、问题来源,多线程使用Libcurl导致程序跑一段时间后自己退出,没有明显的异常。找不到合适的BUG。

 

最后通过查看资料和网上找的一些文章,发现,原来是信号处理的问题:

 

 

CURLOPT_NOSIGNAL


Pass a long. If it is 1, libcurl will not use any functions that install signal handlers or any functions that cause signals to be sent to the process. This option is mainly here to allow multi-threaded unix applications to still set/use all timeout options etc, without risking getting signals. (Added in 7.10)

If this option is set and libcurl has been built with the standard name resolver, timeouts will not occur while the name resolve takes place. Consider building libcurl with c-ares support to enable asynchronous DNS lookups, which enables nice timeouts for name resolves without signals.

Setting CURLOPT_NOSIGNAL to 1 makes libcurl NOT ask the system to ignore SIGPIPE signals, which otherwise are sent by the system when trying to send data to a socket which is closed in the other end. libcurl makes an effort to never cause such SIGPIPEs to trigger, but some operating systems have no way to avoid them and even on those that have there are some corner cases when they may still happen, contrary to our desire. 

 

就是当多个线程都使用超时处理的时候,同时主线程中有sleep或是wait等操作。如果不设置这个选项,libcurl将会发信号打断这个wait从而导致程序退出。

 

所以,在使用的时候把这个选项设置成1就可以了.

curl_setopt(curl, CURLOPT_NOSIGNAL, 1L);

 

2、关于libcurl库的初始化和关闭:curl_global_init()和curl_global_cleanup()

这两个函数并不是线程安全的。所以只能在主线程中进行一次的初始化和清除。

虽然这个不是一定就会有问题,但是如果不这样处理还是有概率发生的。

Linux 定时器alarm()

 

========================================================

系统中的每个进程都有一个私有的闹钟。这个闹钟很像一个计时器,可以设置在一定秒数后闹钟。时间一到,时钟就发送一个信号SIGALRM到进程。

 

函数原型:unsigned int alarm(unsigned int seconds);
头文件:#include<unistd.h>
函数说明: alarm()用来设置信号SIGALRM在经过参数seconds指定的秒数后,传送给目前的进程。如果参数seconds为0,则之前设置的闹钟会被取消,并将剩下的时间返回。
返回值:如果调用此alarm()前,进程已经设置了闹钟时间,则返回上一个闹钟时间的剩余时间,否则返回0。 出错返回-1。

例1:

int main(int argc, char *argv[])
{

 unsigned int  timeleft;

 

 printf( "Set the alarm and sleep\n" );
 alarm( 10 );
 sleep( 5 );

 

 timeleft = alarm( 0 ); //获得上一个闹钟的剩余时间:5秒
 printf( "\Time left before cancel, and rearm: %d\n", timeleft );

 

 alarm( timeleft );

 

 printf( "\Hanging around, waiting to die\n" );
 pause(); //让进程暂停直到信号出现

 return EXIT_SUCCESS;

}

 

运行结果:

首先打   Set the alarm and sleep

5秒后打印  Time left before cancel, and rearm: 5

           Hanging around, waiting to die

再经过5秒,程序结束


例2:

static void timer(int sig)
{
 static int count=0;
 count++;


 printf("\ncount = %d\n", count);

    if(sig == SIGALRM)
    {
        printf("timer\n");
    }

 

 signal(SIGALRM, timer);
 alarm(1);

 

  if (count == 5)
    alarm(0);
    return;
}

 

int main(int argc, char *argv[])
{
 signal(SIGALRM, timer);
 alarm(1);
 while(1);

}

 

除非进程为SIGALRM设置了处理函数,否则信号将杀死这个进程。比较下例中signal(SIGALRM, wakeup);语句打开与关闭的区别。

例3:

void wakeup()
{
 printf("Wake Up!\n");
}

void main(int argc, char *argv[])
{
 printf("sleep 3 seconds!\n");
 //signal(SIGALRM, wakeup);
 alarm(3);
 pause();
 printf("Waken!\n");
}

 

计时器的另一个用途是调度一个在将来的某个时刻发生的动作同时做些其他事情。调度一个将要发生的动作很简单,通过调用alarm来设置计时器,然后继续做别的事情。当计时器计时到0时,信号发送,处理函数被调用。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值