记一次ssl问题测试

55 篇文章 4 订阅

项目中通过ulxmlrpc实现https通信,两个线程分别运行https server端以及https client端。调试过程中发现报错:

6240:error:140A90F1:SSL routines:SSL_CTX_new:unable to load ssl2 md5 routines:.\ssl\ssl_lib.c:1804:

经排查问题为未进行库导入,需以下代码:

    SSL_library_init();
    SSLeay_add_ssl_algorithms();
    SSL_load_error_strings();

多线程导致需进行多次库导入以及error信息导入,考虑在主线程中进行初始化或者分别在不同线程中进行初始化,在主线程中初始化会导致程序耦合性提高,不同线程中进行初始化考虑到server端进行一次初始化,client端每次使用就需进行一次初始化,需考虑是否会导致内存泄漏。

在linux环境下进行测试:

#include<iostream>
#include <string.h>
#include<pthread.h>

#include <openssl/bio.h>
#include <openssl/crypto.h>
#include <openssl/evp.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <unistd.h>

void test_ssl(void)
{
    SSL_library_init();
    SSLeay_add_ssl_algorithms();
    SSL_load_error_strings();    

}

void * test1(void*)
{
    unsigned i = 0;
    while(1)
    {
     std::cout<<"thread 1 "<< i++ <<std::endl;
     SSL_METHOD *meth = (SSL_METHOD *)SSLv23_method();
     SSL_CTX *ssl_ctx = SSL_CTX_new (meth);
     if (!ssl_ctx)
     {
          std::cout<<"thread 1 error"<<std::endl;
          ERR_print_errors_fp(stdout);
          exit(2);

     }
     if (ssl_ctx != 0)
     SSL_CTX_free(ssl_ctx);
     ssl_ctx = 0;
     sleep(1);
    }
}
void * test2(void*)
{   unsigned i = 0;
    while(1)
    {
     std::cout<<"thread 2 "<< i++ <<std::endl;
     SSL_METHOD *meth = (SSL_METHOD *)SSLv23_method();
     SSL_CTX *ssl_ctx = SSL_CTX_new (meth);
     if (!ssl_ctx)
     {
          std::cout<<"thread 2 error"<<std::endl;
          ERR_print_errors_fp(stdout);
          exit(2);

     }
     if (ssl_ctx != 0)
     SSL_CTX_free(ssl_ctx);
     ssl_ctx = 0;
     sleep(1);
    }
}
void * test3(void*)
{ unsigned i = 0;
    while(1)
    {
     std::cout<<"thread 3"<< i++ <<std::endl;
     SSL_METHOD *meth = (SSL_METHOD *)SSLv23_method();
     SSL_CTX *ssl_ctx = SSL_CTX_new (meth);
     if (!ssl_ctx)
     {
          std::cout<<"thread 3 error"<<std::endl;
          ERR_print_errors_fp(stdout);
          exit(2);

     }
     if (ssl_ctx != 0)
     SSL_CTX_free(ssl_ctx);
     ssl_ctx = 0;
     sleep(1);
    }
}
int main(int argc,char *argv[])
{

    test_ssl();     
    pthread_t t1;
    pthread_t t2;
    pthread_t t3;
    pthread_create(&t1,NULL,test1,NULL);
    pthread_create(&t2,NULL,test2,NULL);
    pthread_create(&t3,NULL,test3,NULL);
    
    while(1);

    return 0;
}
 

测试结果发现主线程中进行统一初始化,各个线程可以正常进行SSL_CTX_new操作。

测试多线程进行初始化:

#include<iostream>
#include <string.h>
#include<pthread.h>

#include <openssl/bio.h>
#include <openssl/crypto.h>
#include <openssl/evp.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <unistd.h>

void test_ssl(void)
{
    SSL_library_init();
    SSLeay_add_ssl_algorithms();
    SSL_load_error_strings();    

}

void * test1(void*)
{
    unsigned i = 0;
    while(1)
    {

      test_ssl();     
     std::cout<<"thread 1 "<< i++ <<std::endl;
     SSL_METHOD *meth = (SSL_METHOD *)SSLv23_method();
     SSL_CTX *ssl_ctx = SSL_CTX_new (meth);
     if (!ssl_ctx)
     {
          std::cout<<"thread 1 error"<<std::endl;
          ERR_print_errors_fp(stdout);
          exit(2);

     }
     if (ssl_ctx != 0)
     SSL_CTX_free(ssl_ctx);
     ssl_ctx = 0;
     usleep(100);
    }
}
void * test2(void*)
{   unsigned i = 0;
    while(1)
    {

      test_ssl();     
     std::cout<<"thread 2 "<< i++ <<std::endl;
     SSL_METHOD *meth = (SSL_METHOD *)SSLv23_method();
     SSL_CTX *ssl_ctx = SSL_CTX_new (meth);
     if (!ssl_ctx)
     {
          std::cout<<"thread 2 error"<<std::endl;
          ERR_print_errors_fp(stdout);
          exit(2);

     }
     if (ssl_ctx != 0)
     SSL_CTX_free(ssl_ctx);
     ssl_ctx = 0;
     usleep(100);
    }
}
void * test3(void*)
{ unsigned i = 0;
    while(1)
    {

      test_ssl();     
     std::cout<<"thread 3"<< i++ <<std::endl;
     SSL_METHOD *meth = (SSL_METHOD *)SSLv23_method();
     SSL_CTX *ssl_ctx = SSL_CTX_new (meth);
     if (!ssl_ctx)
     {
          std::cout<<"thread 3 error"<<std::endl;
          ERR_print_errors_fp(stdout);
          exit(2);

     }
     if (ssl_ctx != 0)
     SSL_CTX_free(ssl_ctx);
     ssl_ctx = 0;
     usleep(100);
    }
}
int main(int argc,char *argv[])
{

    //test_ssl();     
    pthread_t t1;
    pthread_t t2;
    pthread_t t3;
    pthread_create(&t1,NULL,test1,NULL);
    pthread_create(&t2,NULL,test2,NULL);
    pthread_create(&t3,NULL,test3,NULL);
    
    while(1);

    return 0;
}

运行测试代码top进行内存占用查看,测试进行100w次线程循环,内存未见明显增加,基本保持0.2%。

测试在一个线程中进行导入库等操作:

#include<iostream>
#include <string.h>
#include<pthread.h>

#include <openssl/bio.h>
#include <openssl/crypto.h>
#include <openssl/evp.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <unistd.h>

void test_ssl(void)
{
    SSL_library_init();
    SSLeay_add_ssl_algorithms();
    SSL_load_error_strings();    

}

void * test1(void*)
{
    sleep(1);
    unsigned i = 0;
    while(1)
    {
     std::cout<<"thread 1 "<< i++ <<std::endl;
     SSL_METHOD *meth = (SSL_METHOD *)SSLv23_method();
     SSL_CTX *ssl_ctx = SSL_CTX_new (meth);
     if (!ssl_ctx)
     {
          std::cout<<"thread 1 error"<<std::endl;
          ERR_print_errors_fp(stdout);
          exit(2);

     }
     if (ssl_ctx != 0)
     SSL_CTX_free(ssl_ctx);
     ssl_ctx = 0;
     sleep(1);
    }
}
void * test2(void*)
{   unsigned i = 0;
    sleep(1);
    while(1)
    {
     std::cout<<"thread 2 "<< i++ <<std::endl;
     SSL_METHOD *meth = (SSL_METHOD *)SSLv23_method();
     SSL_CTX *ssl_ctx = SSL_CTX_new (meth);
     if (!ssl_ctx)
     {
          std::cout<<"thread 2 error"<<std::endl;
          ERR_print_errors_fp(stdout);
          exit(2);

     }
     if (ssl_ctx != 0)
     SSL_CTX_free(ssl_ctx);
     ssl_ctx = 0;
     sleep(1);
    }
}
void * test3(void*)
{ unsigned i = 0;
    while(1)
    {
     test_ssl();     
     std::cout<<"thread 3"<< i++ <<std::endl;
     SSL_METHOD *meth = (SSL_METHOD *)SSLv23_method();
     SSL_CTX *ssl_ctx = SSL_CTX_new (meth);
     if (!ssl_ctx)
     {
          std::cout<<"thread 3 error"<<std::endl;
          ERR_print_errors_fp(stdout);
          exit(2);

     }
     if (ssl_ctx != 0)
     SSL_CTX_free(ssl_ctx);
     ssl_ctx = 0;
     sleep(1);
    }
}
int main(int argc,char *argv[])
{

     //test_ssl();     
    pthread_t t1;
    pthread_t t2;
    pthread_t t3;
    pthread_create(&t1,NULL,test1,NULL);
    pthread_create(&t2,NULL,test2,NULL);
    pthread_create(&t3,NULL,test3,NULL);
    
    while(1);

    return 0;
}
测试发现线程test3先运行并进行库导入操作,其他线程依旧可以进行SSL_CTX_new申请操作。

ps:1、注意需对ssl_ctx进行释放,否则会影响测试效果。

     2、g++ -g ssl_test.cpp -I /usr/local/ssl/include -L /usr/local/ssl/lib -lssl -lcrypto -ldl -pthread进行编译

     3、查找参考资料导入库等操作属于全局操作,由于算法等数据结构以及插入时查找节点逻辑,多次初始化并不会导致重复节点,因此不会导致内存泄漏。

     4、在window项目中在主线程中统一初始化出现部分线程可以进行SSL_CTX_new申请,部分线程无法进行SSL_CTX_new申请的现象,原因还在继续查找。

     5、由于操作对象为全局变量,进行导入等操作是要考虑多线程资源保护,可使用互斥锁pthread_mutex进行保护。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值