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

            導航

            統計

            常用鏈接

            留言簿(3)

            隨筆分類

            隨筆檔案

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            久久被窝电影亚洲爽爽爽| 久久这里只有精品久久| 丰满少妇人妻久久久久久4| 国产精品一久久香蕉国产线看观看| 久久精品国产亚洲AV香蕉| 亚洲色大成网站WWW久久九九| 亚洲AV无码1区2区久久| 久久er99热精品一区二区| 日韩亚洲欧美久久久www综合网| 亚洲精品高清国产一久久| 久久久久亚洲av成人无码电影| 人妻无码久久精品| 九九精品99久久久香蕉| 久久无码国产| 国产精品毛片久久久久久久| 久久国产精品免费一区二区三区| 久久综合伊人77777| 久久精品国产亚洲77777| 久久九色综合九色99伊人| 亚洲午夜久久久久久久久电影网| 国产精品成人久久久久久久| 久久热这里只有精品在线观看| 精品一区二区久久久久久久网站| 久久毛片一区二区| 色诱久久久久综合网ywww| 91麻豆精品国产91久久久久久| 日韩av无码久久精品免费| 精品久久久久久国产三级| 国内精品久久久久久99| 久久久午夜精品福利内容| 久久精品成人一区二区三区| 人妻丰满AV无码久久不卡 | 久久久久久久综合日本亚洲| 精品久久久久久久久免费影院| 久久青草国产精品一区| 亚洲第一极品精品无码久久| 色偷偷88欧美精品久久久| 久久久久亚洲AV成人网人人网站| 国产成人精品久久| 99久久精品这里只有精品| 久久精品九九亚洲精品天堂|