• <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 多彩人生 閱讀(2657) 評論(0)  編輯 收藏 引用

            導航

            統計

            常用鏈接

            留言簿(3)

            隨筆分類

            隨筆檔案

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            久久久99精品成人片中文字幕 | 亚洲欧美伊人久久综合一区二区| 国产精品免费久久久久久久久| 国产成人精品久久亚洲| 奇米影视7777久久精品人人爽| 亚洲国产精品一区二区久久hs| 久久国产精品-久久精品| 久久99久久无码毛片一区二区| 国产成人综合久久精品红| 2021久久精品国产99国产精品| 国产精品成人久久久久三级午夜电影 | 奇米影视7777久久精品| 亚洲国产精品久久久久久| 日日狠狠久久偷偷色综合免费| 久久久久人妻一区精品色| 午夜精品久久久久久影视777| 99国产欧美精品久久久蜜芽| 亚洲综合久久夜AV | 久久久久久a亚洲欧洲aⅴ| 久久婷婷五月综合成人D啪| 国产精品嫩草影院久久| 久久66热人妻偷产精品9| 国产精品久久久久a影院| 久久久久久av无码免费看大片| 国产精品久久久久久影院| 看久久久久久a级毛片| 欧美精品国产综合久久| 亚洲精品无码久久不卡| 99久久精品免费看国产| 国产成人久久精品区一区二区| 偷窥少妇久久久久久久久| 婷婷久久综合| 思思久久99热免费精品6| 热综合一本伊人久久精品| 精品视频久久久久| 久久久久久国产精品美女| 久久久精品波多野结衣| 亚洲?V乱码久久精品蜜桃 | 一本色道久久88精品综合| 久久婷婷五月综合色奶水99啪| 久久福利资源国产精品999|