Skip to content

Crash on appllication exit while SSL is enabled (threadpool destructor is not called?) #1482

Open
@StepchenkoA

Description

@StepchenkoA

On Linux (RH6, CppRest 2.10.16, Azure Storage SDK 7.3.1, Gcc 8.3.1) application is crashed with segmentation fault

Code snippet looks like:

//main.c
int main() {
foo_init();
foo_do();
foo_close();
}

//foo.c
foo_init() {
crossplat::threadpool::initialize_with_threads(40);
}
foo_do() {
//do something
}
foo_close() {
crossplat::threadpool::shared_instance().stop();
}

Backtrace looks like this:

#0 0x0000003557c75f8b in malloc_consolidate () from /lib64/libc.so.6
#1 0x0000003557c78c88 in _int_free () from /lib64/libc.so.6
#2 0x00007f491fafbc73 in bio_free () from libcrypto.so.1.1
#3 0x00007f491faf96aa in BIO_free () from libcrypto.so.1.1
#4 0x00007f491fafa9f4 in BIO_free_all () from libcrypto.so.1.1
#5 0x00007f491f7efa7f in SSL_free () from libssl.so.1.1
#6 0x0000000000e2d1e4 in std::_Sp_counted_ptr_inplace<web::http::client::details::asio_connection, std::allocatorweb::http::client::details::asio_connection, (__gnu_cxx::_Lock_policy)2>::_M_dispose() ()
#7 0x0000000000e2b9b3 in std::_Rb_tree<std::basic_string<char, std::char_traits, std::allocator >, std::pair<std::basic_string<char, std::char_traits, std::allocator > const, web::http::client::details::connection_pool_stackweb::http::client::details::asio_connection >, std::_Select1st<std::pair<std::basic_string<char, std::char_traits, std::allocator > const, web::http::client::details::connection_pool_stackweb::http::client::details::asio_connection > >, std::less<std::basic_string<char, std::char_traits, std::allocator > >, std::allocator<std::pair<std::basic_string<char, std::char_traits, std::allocator > const, web::http::client::details::connection_pool_stackweb::http::client::details::asio_connection > > >::_M_erase(std::_Rb_tree_node<std::pair<std::basic_string<char, std::char_traits, std::allocator > const, web::http::client::details::connection_pool_stackweb::http::client::details::asio_connection > >*) ()
#8 0x0000000000e2d10a in std::_Sp_counted_ptr_inplace<web::http::client::details::asio_connection_pool, std::allocatorweb::http::client::details::asio_connection_pool, (__gnu_cxx::_Lock_policy)2>::_M_dispose() ()
#9 0x0000000000a4d358 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release (this=0x2a10d50) at /opt/rh/devtoolset-8/root/usr/include/c++/8/bits/shared_ptr_base.h:155
#10 0x0000000000e2a17a in std::_Sp_counted_ptr_inplace<web::http::client::details::asio_client, std::allocatorweb::http::client::details::asio_client, (__gnu_cxx::_Lock_policy)2>::_M_dispose() ()
#11 0x0000000000deeab7 in std::_Sp_counted_ptr_inplace<web::http::client::http_pipeline, std::allocatorweb::http::client::http_pipeline, (__gnu_cxx::_Lock_policy)2>::_M_dispose() ()
#12 0x0000000000a4d358 in std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release (this=0x2a0fd00) at /opt/rh/devtoolset-8/root/usr/include/c++/8/bits/shared_ptr_base.h:155
#13 0x0000000000d2c747 in std::map<std::basic_string<char, std::char_traits, std::allocator >, std::shared_ptrweb::http::client::http_client, std::less<std::basic_string<char, std::char_traits, std::allocator > >, std::allocator<std::pair<std::basic_string<char, std::char_traits, std::allocator > const, std::shared_ptrweb::http::client::http_client > > >::~map() ()
#14 0x0000003557c35a02 in exit () from /lib64/libc.so.6
#15 0x0000003557c1ed27 in __libc_start_main () from /lib64/libc.so.6
#16 0x000000000047dcd1 in _start ()

The problem is raised in such conditions:

  1. Azure Storage SDK opens more than 1 connection to Azure
  2. Static variable boost::asio::io_service& s_service is deleted from http_client_reusable class. So, any indirect initialization

It looks that SSL_free() is called on structure while socket still is listen state

Workaround to fix the problem:
Either:
return back initialization of s_service or implement own global static variable with the same initialization:
boost::asio::io_service& g_service = crossplat::threadpool::shared_instance().service();
Or
put sleep() call before closing application
Or
call manually destructor of threadpool: crossplat::threadpool::shared_instance().~threadpool()

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions