Code Monkey home page Code Monkey logo

Comments (33)

gandalf000 avatar gandalf000 commented on May 28, 2024

rpc_byte_stream的引用计数有问题? 导致对象析构?

from sofa-pbrpc.

cyshi avatar cyshi commented on May 28, 2024

Hi @gandalf000

能不能提供下你用的版本,或者看看最新的主干代码会不会有这个问题(之前版本io_service和socket的释放顺序有些问题,新版已经调整了)

from sofa-pbrpc.

yvxiang avatar yvxiang commented on May 28, 2024

·@cyshi 今天同样遇到了这个问题,core的位置跟上面的同学一模一样,sofa-pbrpc的版本为1.0.0
等下我看看最新的版本

from sofa-pbrpc.

yvxiang avatar yvxiang commented on May 28, 2024

@ysh @gandalf000 我试了下,大体情况如下(拿tera源码作实验,出现core的是编译后产生的teracli二进制,表现为可以正常运行,但是在全局析构函数中,core在上述位置):
(1)在ubumtu 14.04发行版下,无论使用哪个版本的sofa-pbrpc,均会在上述地方core。
(2)同样版本的源码,在ubuntu 14.10下,没有任何问题。
(3)ldd显示,teracli所依赖的动态链接库中,libstdc++的版本有所不同,在可以正常运行的ubuntu14.10中,libstdc++的版本号为6.0.20,而在core的ubuntu14.04下,libstdc++的版本号为6.0.19。
(4)将ubuntu14.10中的6.0.20版本复制到ubuntu14.04中,动态加载时用LDD_PRELOAD指定使用6.0.20版本,可恢复正常运行。

所以看起来像是一些库版本之间的兼容性问题

.

from sofa-pbrpc.

cyshi avatar cyshi commented on May 28, 2024

Hi @yvxiang 新版中我只修了server,你可以在 rpc_client_impl.cc 中尝试调整Stop()函数的_work_thread_group->stop();这句到ClearStreams()后面,看看是否还会core

from sofa-pbrpc.

yvxiang avatar yvxiang commented on May 28, 2024

@cyshi 还是会core的,在析构全局变量,调用RpcClientImpl::Stop()时core了。如果把RpcClient::~RpcClient()中的ShutDown()去掉,让Stop()在RpcClientImpl析构时执行,就没问题了。
基本上所有地方都是shared_ptr,想不通为啥……

from sofa-pbrpc.

qinzuoyan avatar qinzuoyan commented on May 28, 2024

@yvxiang 是否可以弄一个简单的sample code来让我在ubuntu 14.04下面重现这个core?而不需要编译teracli

from sofa-pbrpc.

yvxiang avatar yvxiang commented on May 28, 2024

@qinzuoyan 可以用sample/echo这个作为例子:
(1) 不作任何改动时,可以正常运行。
(2) 将rpc_client这个main函数内的局部变量改为全局变量时,会出现core。dump出来的结果显示,是在RpcByteStream::close()中调用shutdown时,线程池中的线程挂了。
(3) 如果在main函数结束之前,手动调用一下全局rpc_client的Shutdown() 函数,则不会core。
(4) teracli中,正是有一个全局的静态变量m_rpc_client,所以和这里的情况一样。
这里 提到了由于boost的原因可能导致类似的错误,但是还不完全一样。
难道全局析构会有什么不同吗……

from sofa-pbrpc.

qinzuoyan avatar qinzuoyan commented on May 28, 2024

查了许久也没有找到根本原因,不过有个简单的修复办法,参见 #47 。另外目前还是不要轻易修改析构函数中的顺序吧,怕引出新的问题。

from sofa-pbrpc.

cyshi avatar cyshi commented on May 28, 2024

@yvxiang 给的复现方法,现在基本能确认是全局变量析构顺序导致程序coredump

第一个全局变量是 rpc_client,第二个比较隐蔽是 boost error.hpp中的misc_category

ubuntu下程序coredump是因为先构造了rpc_client,之后构造了 misc_category,所以析构的时候misc_category先于rpc_client释放,rpc_client->Stop() 的过程中(主线程中),asio的IO线程被唤醒处理错误,这时拿到的error中的m_cat(就是misc_category)实际已经被释放过,虚函数表被清空,所以程序异常退出

所以要修复这个问题,就要保证misc_category先于rpc_client构造,有一种改法是将<boost/asio.hpp>置入rpc_client.h中,明确告诉编译器依赖关系,保证misc_category先构造 @qinzuoyan 可以看看这样有没有问题 参见 #48

from sofa-pbrpc.

qinzuoyan avatar qinzuoyan commented on May 28, 2024

@cyshi 找出了问题根源。我之前也一直按照全局变量析构顺序的方向追,但是只考虑到boost::system::system_category和boost::system::generic_category(这两者的析构顺序没有问题),并没有想到是boost::asio::error里面的category的析构顺序,所以百思不得其解,多谢@cyshi 帮我解了这个心头之结。

@cyshi 的修复方式 #48 确实能解决这个问题,但是我觉得带来一个新的问题,就是sofa-pbrpc对外的头文件将依赖boost。
目前,sofa-pbrpc的头文件和库都完全不依赖boost:

  • 对于头文件,所有对用户暴露的头文件都不引用boost的头文件,为此还专门把boost的smart_ptr剥离出来(参见src/sofa/pbrpc/smart_ptr)
  • 对于库文件,为了避免唯一可能的依赖libboost_system.a,专门把boost_system_error_code.cc编译到里libsofa-pbrpc.a中(参见src/sofa/pbrpc/boost_system_error_code.cc)

我修改了demo下面的Makefile,可以看到对boost的头文件和库都是完全无依赖的。

所以,为了保持这一点,我觉得这样修改可能更好:

  • 在RpcClient和RpcServer的构造函数中调用touch_boost_error_category()来影响全局变量的构建顺序,通过测试,确实可行
  • 在RpcMessageStream的on_read_some()和on_write_some()中检查是否is_connected(),虽然这里对解决该问题其实已经不是必要的,但是加上也是合理的

参见pull request:#47

from sofa-pbrpc.

cyshi avatar cyshi commented on May 28, 2024

@qinzuoyan 的修复方式更合理 merged

from sofa-pbrpc.

yvxiang avatar yvxiang commented on May 28, 2024

赞~

from sofa-pbrpc.

gandalf000 avatar gandalf000 commented on May 28, 2024

merge了48的改动之后,发现还是一样的core dump。

from sofa-pbrpc.

qinzuoyan avatar qinzuoyan commented on May 28, 2024

@gandalf000 可以稳定复现吗?

from sofa-pbrpc.

gandalf000 avatar gandalf000 commented on May 28, 2024

387 #0 0x00007f40a684f625 in raise () from /lib64/libc.so.6
388 #1 0x00007f40a6850e05 in abort () from /lib64/libc.so.6
389 #2 0x00007f40a70aaa55 in __gnu_cxx::__verbose_terminate_handler () at ../../.././libstdc++-v3/libsupc++/vterminate.cc:95
390 #3 0x00007f40a70a8bf6 in __cxxabiv1::__terminate (handler=) at ../../.././libstdc++-v3/libsupc++/eh_terminate.cc:38
391 #4 0x00007f40a70a8c23 in std::terminate () at ../../.././libstdc++-v3/libsupc++/eh_terminate.cc:48
392 #5 0x00007f40a70a96df in __cxxabiv1::__cxa_pure_virtual () at ../../.././libstdc++-v3/libsupc++/pure.cc:50
393 #6 0x00000000005c44e5 in sofa::pbrpc::RpcMessageStreamsofa::pbrpc::shared_ptr<sofa::pbrpc::RpcControllerImpl >::on_read_some(boost::system::error_code const&, unsigned long) ()
394 #7 0x00000000005b24e0 in boost::asio::detail::reactive_socket_recv_op<boost::asio::mutable_buffers_1, boost::bi::bind_t<void, boost::mfi::mf2<void, sofa::pbrpc::RpcByteStream, boost::system::error_code const&, unsigned long>, boo st::bi::list3boost::bi::value<sofa::pbrpc::shared_ptr<sofa::pbrpc::RpcByteStream >, boost::arg<1>, boost::arg<2> > > >::do_complete(boost::asio::detail::task_io_service, boost::asio::detail::task_io_service_operation, boost::s ystem::error_code const&, unsigned long) ()
395 #8 0x00000000005b4fb9 in boost::asio::detail::epoll_reactor::descriptor_state::do_complete(boost::asio::detail::task_io_service
, boost::asio::detail::task_io_service_operation
, boost::system::error_code const&, unsigned long) ()
396 #9 0x00000000005b793e in boost::asio::detail::task_io_service::run(boost::system::error_code&) ()
397 #10 0x00000000005b82ae in sofa::pbrpc::ThreadGroupImpl::thread_run(void*) ()
398 #11 0x00007f40a77cf9d1 in start_thread () from /lib64/libpthread.so.0
399 #12 0x00007f40a69058fd in clone () from /lib64/libc.so.6

发生的概率还挺大的。

from sofa-pbrpc.

gandalf000 avatar gandalf000 commented on May 28, 2024

看堆栈,应该是这个rpc_byte_stream被析构了?

from sofa-pbrpc.

qinzuoyan avatar qinzuoyan commented on May 28, 2024

用debug模式吧

from sofa-pbrpc.

gandalf000 avatar gandalf000 commented on May 28, 2024

开了DEBUG模式。
#0 0x00007f33d2b75625 in raise () from /lib64/libc.so.6
#1 0x00007f33d2b76e05 in abort () from /lib64/libc.so.6
#2 0x00007f33d33d0a55 in __gnu_cxx::__verbose_terminate_handler () at ../../.././libstdc++-v3/libsupc++/vterminate.cc:95
#3 0x00007f33d33cebf6 in __cxxabiv1::__terminate (handler=) at ../../.././libstdc++-v3/libsupc++/eh_terminate.cc:38
#4 0x00007f33d33cec23 in std::terminate () at ../../.././libstdc++-v3/libsupc++/eh_terminate.cc:48
#5 0x00007f33d33cf6df in __cxxabiv1::__cxa_pure_virtual () at ../../.././libstdc++-v3/libsupc++/pure.cc:50
#6 0x00000000005a9b0b in boost::system::error_code::message (this=0x7f33c8f94a60) at ../../boost_1_53_0/boost/system/error_code.hpp:350
#7 0x00000000005dee6f in sofa::pbrpc::RpcMessageStreamsofa::pbrpc::shared_ptr<sofa::pbrpc::RpcControllerImpl >::on_read_some (this=0x7f339c0b5600, error=..., bytes_transferred=0)
at src/sofa/pbrpc/rpc_message_stream.h:237
#8 0x00000000005dd197 in boost::_mfi::mf2<void, sofa::pbrpc::RpcByteStream, boost::system::error_code const&, unsigned long>::callsofa::pbrpc::shared_ptr<sofa::pbrpc::RpcByteStream, boost::system::error_code const, unsigned long> (this=0x7f33c8f94a40, u=..., b1=..., b2=@0x7f33c8f94850: 0) at ../../boost_1_53_0/boost/bind/mem_fn_template.hpp:271
#9 0x00000000005dcf15 in boost::_mfi::mf2<void, sofa::pbrpc::RpcByteStream, boost::system::error_code const&, unsigned long>::operator()sofa::pbrpc::shared_ptr<sofa::pbrpc::RpcByteStream > (
this=0x7f33c8f94a40, u=..., a1=..., a2=0) at ../../boost_1_53_0/boost/bind/mem_fn_template.hpp:286
#10 0x00000000005dca58 in boost::_bi::list3boost::_bi::value<sofa::pbrpc::shared_ptr<sofa::pbrpc::RpcByteStream >, boost::arg<1>, boost::arg<2> >::operator()<boost::_mfi::mf2<void, sofa::pbrpc::RpcByteStream, boost::system::error_code const&, unsigned long>, boost::_bi::list2<boost::system::error_code const&, unsigned long const&> > (this=0x7f33c8f94a50, f=..., a=...)
at ../../boost_1_53_0/boost/bind/bind.hpp:392
#11 0x00000000005dc674 in boost::_bi::bind_t<void, boost::_mfi::mf2<void, sofa::pbrpc::RpcByteStream, boost::system::error_code const&, unsigned long>, boost::_bi::list3boost::_bi::value<sofa::pbrpc::shared_ptr<sofa::pbrpc::RpcByteStream >, boost::arg<1>, boost::arg<2> > >::operator()<boost::system::error_code, unsigned long> (this=0x7f33c8f94a40, a1=..., a2=@0x7f33c8f94a70: 0)
at ../../boost_1_53_0/boost/bind/bind_template.hpp:102

from sofa-pbrpc.

qinzuoyan avatar qinzuoyan commented on May 28, 2024

看到了,你的RpcClient是怎么使用的?是放在全局变量里吗?

from sofa-pbrpc.

gandalf000 avatar gandalf000 commented on May 28, 2024

这个是rpc server 的回调还是rpc client的?
没有使用全局变量

from sofa-pbrpc.

gandalf000 avatar gandalf000 commented on May 28, 2024

我这个进程是一个rpc server,收消息,同时用rpc client调用其它rpc service。

from sofa-pbrpc.

gandalf000 avatar gandalf000 commented on May 28, 2024

我print了status_, 发现是connected状态。

from sofa-pbrpc.

qinzuoyan avatar qinzuoyan commented on May 28, 2024

这个是rpc client的调用,你的rpc client是怎么使用的?

from sofa-pbrpc.

gandalf000 avatar gandalf000 commented on May 28, 2024

rpc_client是一个对象的成员变量, 两个stub对象共享,main函数退出时候,直接调用的exit。没有调用任何stop和析构函数。

from sofa-pbrpc.

gandalf000 avatar gandalf000 commented on May 28, 2024

并且只在进程exit的时候才core,正常运行不core。

from sofa-pbrpc.

gandalf000 avatar gandalf000 commented on May 28, 2024

rpc_client是进程启动的时候创建的,常驻。

from sofa-pbrpc.

gandalf000 avatar gandalf000 commented on May 28, 2024

需要在退出之前,去调用shutdown或者析构rpc client么?

from sofa-pbrpc.

qinzuoyan avatar qinzuoyan commented on May 28, 2024

了解了,这是进程退出造成的问题:

  • rpc_client是一个常驻对象,即使在exit的时候,也不会调用Shutdown()或者析构函数,其内部各种工作线程会持续运行
  • 在exit时,会析构全局对象,包括boost中的各种error_category
  • 当error_category析构后,rpc_client的工作线程还在运行,并且is_connected()也是true,所以会运行到on_read_some()中相关代码,存取error_category,然后出core(出core原因可参见上面的讨论)

解决办法:在main()函数结束前,通过某种办法主动调用RpcClient::Shutdown()就可以了

from sofa-pbrpc.

gandalf000 avatar gandalf000 commented on May 28, 2024

is_connected()的逻辑判断需要添加么?

from sofa-pbrpc.

qinzuoyan avatar qinzuoyan commented on May 28, 2024

其他都不用做,在退出前调用RpcClient::Shutdown()或者RpcClient的析构函数就可以了

from sofa-pbrpc.

gandalf000 avatar gandalf000 commented on May 28, 2024

RpcClient::Shutdown()了之后,这个对象就不能再使用了对吧,如果再使用看起来会core掉。

from sofa-pbrpc.

qinzuoyan avatar qinzuoyan commented on May 28, 2024

是的,最好不要重用。
RpcClient是建议长期持有的,一个进程最好只有一个实例,尽量不要频繁创建和删除。

from sofa-pbrpc.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.