• <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毛片| 成人国内精品久久久久影院| 国产精品99久久久久久董美香 | 久久亚洲美女精品国产精品| 欧美牲交A欧牲交aⅴ久久| 久久电影网一区| 色妞色综合久久夜夜| 国产精品久久久久影视不卡| 久久亚洲欧洲国产综合| 久久人人爽人人爽人人AV| 精品久久久久久无码中文字幕| 无码国内精品久久人妻| 开心久久婷婷综合中文字幕| 久久久久久九九99精品| 久久精品无码一区二区三区日韩| 伊人色综合久久天天网| 久久国产成人午夜aⅴ影院| 亚洲中文字幕无码一久久区| 久久精品国产亚洲精品| 久久最新精品国产| 99久久国产综合精品麻豆| 青青草原综合久久大伊人| 久久精品99无色码中文字幕| 久久99毛片免费观看不卡| 色综合久久无码五十路人妻| 亚洲人成无码久久电影网站| 久久久久香蕉视频| 久久久精品久久久久久| 国产精品成人99久久久久| 亚洲午夜久久影院| 婷婷综合久久中文字幕| 精品国产福利久久久| 精品九九久久国内精品| 久久精品国产亚洲网站| 97久久精品人人做人人爽| 青青草国产精品久久| 热久久这里只有精品| 久久996热精品xxxx| 欧美大战日韩91综合一区婷婷久久青草| 国产精品久久永久免费| 久久噜噜电影你懂的|