程序在 tls_get_addr 通话时挂起

Program hangs out on tls_get_addr call

我们有一些非常奇怪的问题,程序开始挂起 boost::asio 库使用,从我们在 boost::log 上构建的日志库调用。 只有当我们 link 我们的库在(这个库在我们的任何其他项目中工作得很好)时才会发生这种情况。如果我们在日志初始化之前在模块的初始化函数中创建 boost::asio::ip::tcp::socket 对象,程序就会开始工作,但这当然不是决定。我们还尝试只添加相同大小或更多大小的数组,但不行,只有套接字对象有效。

GDB 显示如下:

#0  __pthread_mutex_unlock_usercnt (mutex=0xf779e504 <_rtld_global+1220>, 
    decr=1) at pthread_mutex_unlock.c:57
#1  0xf777db5e in tls_get_addr_tail (ti=0xf681388c, dtv=0x8bc4410, 
    the_map=0x8b31c48, the_map@entry=0x0) at dl-tls.c:730
#2  0xf778eed9 in ___tls_get_addr (ti=<optimized out>) at dl-tls.c:778
#3  0xf658ba8f in boost::asio::detail::keyword_tss_ptr<boost::asio::detail::call_stack<boost::asio::detail::task_io_service, boost::asio::detail::task_io_service_thread_info>::context>::operator boost::asio::detail::call_stack<boost::asio::detail::task_io_service, boost::asio::detail::task_io_service_thread_info>::context*() const () from /usr/local/lib/libcommon.so.0
#4  0xf6580de5 in boost::asio::detail::call_stack<boost::asio::detail::task_io_service, boost::asio::detail::task_io_service_thread_info>::top() ()
   from /usr/local/lib/libcommon.so.0
#5  0xf657259e in boost::asio::asio_handler_allocate(unsigned int, ...) ()
   from /usr/local/lib/libcommon.so.0
#6  0xf3491aa0 in void* boost_asio_handler_alloc_helpers::allocate<boost::function<void (boost::system::error_code const&)> >(unsigned int, boost::function<void (boost::system::error_code const&)>&) () from /usr/local/lib/liblog.so.0
#7  0xf348f43e in void boost::asio::detail::reactive_socket_service<boost::asio::ip::udp>::async_connect<boost::function<void (boost::system::error_code const&)> >(boost::asio::detail::reactive_socket_service<boost::asio::ip::udp>::implementation_type&, boost::asio::ip::basic_endpoint<boost::asio::ip::udp> const&, boost::function<void (boost::system::error_code const&)>&) ()
#8  0xf348b22a in boost::asio::async_result<boost::asio::handler_type<boost::function<void (boost::system::error_code const&)>, void (boost::system::error_code)>::type>::type boost::asio::datagram_socket_service<boost::asio::ip::udp>::async_connect<boost::function<void (boost::system::error_code const&)> >(boost::asio::detail::reactive_socket_service<boost::asio::ip::udp>::implementation_type&, boost::asio::ip::basic_endpoint<boost::asio::ip::udp> const&, boost::function<void (boost::system::error_code const&)>&&) () from /usr/local/lib/liblog.so.0
#9  0xf3487eab in boost::asio::async_result<boost::asio::handler_type<boost::function<void (boost::system::error_code const&)>, void (boost::system::error_code)>::type>::type boost::asio::basic_socket<boost::asio::ip::udp, boost::asio::datagram_socket_service<boost::asio::ip::udp> >::async_connect<boost::function<void (boost::system::error_code const&)> >(boost::asio::ip::basic_endpoint<boost::asio::ip::udp> const&, boost::function<void (boost::system::error_code const&)>&&)
    () from /usr/local/lib/liblog.so.0
#10 0xf347c50f in syslog_udp_device::syslog_connect() ()
   from /usr/local/lib/liblog.so.0

或者这个:

#0  0xf775de5d in __GI___pthread_mutex_lock (
    mutex=0xf779e504 <_rtld_global+1220>) at ../nptl/pthread_mutex_lock.c:114
#1  0xf777db37 in tls_get_addr_tail (ti=0xf681388c, dtv=0x8bc4410, 
    the_map=0x8b31c48, the_map@entry=0x0) at dl-tls.c:722
#2  0xf778eed9 in ___tls_get_addr (ti=<optimized out>) at dl-tls.c:778

其他同理

无法深入查看,因为它无法在本地计算机上重现,只能在 kube 集群上重现。也许你可以指出我,是什么导致了这种行为?

9 月 22 日,20:23 UTC: valgrind 用 helgrind 显示了一些东西,但它可能是 dataraces,这可能与问题无关。即使在 process -TERM kill 之后,其他工具也只是挂起并且什么也没有指出。今天确定另一个进程(在添加相同的 linkage 之后)也在同一步骤挂起,但我们至少有 3-4 个具有相同库的应用程序,即使在重建之后也能正常工作。看起来像是在某处违反了 ODR。尝试 link 应用程序无法使用与工作应用程序相同的 link 顺序 - 没有区别,仍然挂起。

嗯,那真的很难,但我们确定了问题。那是 glibc 兼容性的问题。构建机器是带有 libc-23 的 jessie,工作机器是带有 libc-19 的 jessie(至少我认为,这是一个问题,可能是其他系统库)。我们非常努力地调试,我们尝试用相同的选项编译我们所有的库(为分叉库构建机器用 -O2 构建它们,而我们的库用 -O0 构建它们),没有帮助。

但是当我们在构建和 运行 上从 jessie 转移到 debian stretch 时 - 一切都开始正常工作(都有 libc-24)。那是艰难而漫长的,因为我们有很多库,但是,这解决了问题。希望你永远不会遇到这样的问题。