• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            colorful

            zc qq:1337220912

             

            libcurl 多線程使用注意事項(補充)——HTTPS,openssl多線程使用加鎖

            問題

            多線程libcurl運行一段時間后出現崩掉,沒有確定的點,沒有確定的URL。一直查看源代碼沒有問題,最后通過debug跟蹤發現是在訪問SSL的時候出現的crash。

            才想起來openssl是不支持多線程的,要自己做加鎖處理。而且libcurl中并沒有支持相關的加鎖操作。


            解決辦法:

            在初始化libcurl的時候為openssl創建一個互斥鎖函數,一個回調函數傳給openss

            openssl鎖l函數原形 :void (* func )(int ,int , const char * ,int)

            設置方式:CRYPTO_set_locking_callback(void (* func )(int ,int , const char * ,int));

            設置這樣一個函數還不夠,另外還要配置一個鎖id回調函數,這個可以參考openssl多線程下的使用相關。

            id函數原形:unsigned int (*func)(void)

            設置方式:CRYPTO_set_id_callback(unsigned int (*func)(void));

            通過這兩個設置就可以解決HTTPS多線程請求出現crash的問題。


            代碼示例:

            下面是引用了libcurl示例的一個代碼

            http://curl.haxx.se/libcurl/c/opensslthreadlock.html

            最關鍵就是,兩個callback的實現,還有初始化鎖(init_locks)和釋放鎖(kill_locks)的位置

            1. #define USE_OPENSSL    
            2.    
            3. #include <stdio.h>  
            4. #include <pthread.h>  
            5. #include <curl/curl.h>  
            6.    
            7. #define NUMT 4  
            8.    
            9. /* we have this global to let the callback get easy access to it */   
            10. static pthread_mutex_t *lockarray;  
            11.    
            12. #ifdef USE_OPENSSL  
            13. #include <openssl/crypto.h>  
            14. static void lock_callback(int mode, int type, char *file, int line)  
            15. {  
            16.   (void)file;  
            17.   (void)line;  
            18.   if (mode & CRYPTO_LOCK) {  
            19.     pthread_mutex_lock(&(lockarray[type]));  
            20.   }  
            21.   else {  
            22.     pthread_mutex_unlock(&(lockarray[type]));  
            23.   }  
            24. }  
            25.    
            26. static unsigned long thread_id(void)  
            27. {  
            28.   unsigned long ret;  
            29.    
            30.   ret=(unsigned long)pthread_self();  
            31.   return(ret);  
            32. }  
            33.    
            34. static void init_locks(void)  
            35. {  
            36.   int i;  
            37.    
            38.   lockarray=(pthread_mutex_t *)OPENSSL_malloc(CRYPTO_num_locks() *  
            39.                                             sizeof(pthread_mutex_t));  
            40.   for (i=0; i<CRYPTO_num_locks(); i++) {  
            41.     pthread_mutex_init(&(lockarray[i]),NULL);  
            42.   }  
            43.    
            44.   CRYPTO_set_id_callback((unsigned long (*)())thread_id);  
            45.   CRYPTO_set_locking_callback((void (*)())lock_callback);  
            46. }  
            47.    
            48. static void kill_locks(void)  
            49. {  
            50.   int i;  
            51.    
            52.   CRYPTO_set_locking_callback(NULL);  
            53.   for (i=0; i<CRYPTO_num_locks(); i++)  
            54.     pthread_mutex_destroy(&(lockarray[i]));  
            55.    
            56.   OPENSSL_free(lockarray);  
            57. }  
            58. #endif  
            59.    
            60. #ifdef USE_GNUTLS  
            61. #include <gcrypt.h>  
            62. #include <errno.h>  
            63.    
            64. GCRY_THREAD_OPTION_PTHREAD_IMPL;  
            65.    
            66. void init_locks(void)  
            67. {  
            68.   gcry_control(GCRYCTL_SET_THREAD_CBS);  
            69. }  
            70.    
            71. #define kill_locks()  
            72. #endif  
            73.    
            74. /* List of URLs to fetch.*/   
            75. const char * const urls[]= {  
            76.   "https://www.example.com/",  
            77.   "https://www2.example.com/",  
            78.   "https://www3.example.com/",  
            79.   "https://www4.example.com/",  
            80. };  
            81.    
            82. static void *pull_one_url(void *url)  
            83. {  
            84.   CURL *curl;  
            85.    
            86.   curl = curl_easy_init();  
            87.   curl_easy_setopt(curl, CURLOPT_URL, url);  
            88.   /* this example doesn't verify the server's certificate, which means we 
            89.      might be downloading stuff from an impostor */   
            90.   curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);  
            91.   curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);  
            92.   curl_easy_perform(curl); /* ignores error */   
            93.   curl_easy_cleanup(curl);  
            94.    
            95.   return NULL;  
            96. }  
            97.    
            98. int main(int argc, char **argv)  
            99. {  
            100.   pthread_t tid[NUMT];  
            101.   int i;  
            102.   int error;  
            103.   (void)argc; /* we don't use any arguments in this example */   
            104.   (void)argv;  
            105.    
            106.   /* Must initialize libcurl before any threads are started */   
            107.   curl_global_init(CURL_GLOBAL_ALL);  
            108.    
            109.   init_locks();  
            110.    
            111.   for(i=0; i< NUMT; i++) {  
            112.     error = pthread_create(&tid[i],  
            113.                            NULL, /* default attributes please */   
            114.                            pull_one_url,  
            115.                            (void *)urls[i]);  
            116.     if(0 != error)  
            117.       fprintf(stderr, "Couldn't run thread number %d, errno %d\n", i, error);  
            118.     else  
            119.       fprintf(stderr, "Thread %d, gets %s\n", i, urls[i]);  
            120.   }  
            121.    
            122.   /* now wait for all threads to terminate */   
            123.   for(i=0; i< NUMT; i++) {  
            124.     error = pthread_join(tid[i], NULL);  
            125.     fprintf(stderr, "Thread %d terminated\n", i);  
            126.   }  
            127.    
            128.   kill_locks();  
            129.    
            130.   return 0;  

            posted on 2013-12-02 17:13 多彩人生 閱讀(2682) 評論(0)  編輯 收藏 引用

            導航

            統計

            常用鏈接

            留言簿(3)

            隨筆分類

            隨筆檔案

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            久久99精品久久久久婷婷| 亚洲综合久久久| 亚洲精品乱码久久久久66| 久久无码中文字幕东京热| 久久亚洲AV成人无码国产| 久久精品国产色蜜蜜麻豆| 亚洲精品成人久久久| 久久久久久亚洲精品成人| 久久天天躁狠狠躁夜夜2020| av无码久久久久久不卡网站| 99久久婷婷国产综合精品草原| 久久99热这里只有精品66| 精品一二三区久久aaa片| 久久亚洲av无码精品浪潮| 波多野结衣AV无码久久一区| 伊人热热久久原色播放www| 久久精品无码专区免费东京热| 久久国产成人午夜AV影院| 久久这里只有精品久久| 波多野结衣AV无码久久一区| 亚洲精品国产成人99久久| 伊人久久久AV老熟妇色| 久久亚洲av无码精品浪潮| 91精品国产综合久久婷婷| 一本色道久久综合亚洲精品| 久久er国产精品免费观看8| 精品国产一区二区三区久久久狼| 久久最新免费视频| 精品久久国产一区二区三区香蕉| 久久久久久国产精品免费无码| 久久婷婷午色综合夜啪| 久久国产高清一区二区三区| 久久精品国产半推半就| 99久久精品无码一区二区毛片| 亚洲国产一成人久久精品| 亚洲精品乱码久久久久久蜜桃不卡 | 久久高清一级毛片| 亚洲国产精品热久久| 欧美精品一区二区精品久久| 久久免费国产精品一区二区| 久久精品中文闷骚内射|