C ++ boost :: asio connection weak_ptr err - PullRequest
       15

C ++ boost :: asio connection weak_ptr err

0 голосов
/ 26 февраля 2019

У меня проблема с C ++ TCP Server (с использованием boost asio).
В обычном клиенте многие клиенты подключаются к серверу нормально.Но если каждый клиент подключается и отключается от сервера 10 раз в секунду, ядро ​​сервера некоторое время.

(1) создает сервер следующим образом:

void ClientConnection::start()
{
  socket_.async_read_some(boost::asio::buffer(buffer_),
      strand_.wrap(
        boost::bind(&connection::handle_read, shared_from_this(),
          boost::asio::placeholders::error,
          boost::asio::placeholders::bytes_transferred)));
}

void ClientConnection::closeSocket() {
    mStrand.post(boost::bind(&ClientConnection::innerCloseSocket, this->shared_from_this()));
}

void ClientConnection::innerCloseSocket() {
    boost::system::error_code error;
    mSocket.close(error);
    LOG_INFO("Close client[" << mClientId << "] socket connection");  //line:216
}

ClientConnection::~ClientConnection() {
}

(2) hand_read вот так:

void ClientConnection::handle_read(const boost::system::error_code& e,
    std::size_t bytes_transferred)
{
  if (!e)
  {
      //read data and use it
  }
  else { //error occurs 
      closeSocket();

      boost::shared_ptr<DisConnectCommand> cmd(new DisConnectCommand());
      cmd->setClient(this->weak_from_this());  //here set this connection weak_ptr

      putCmd(cmd);  //do something in other thread.
  }
}

(3) handle_write наподобие этого:

void ClientConnection::handle_write(const boost::system::error_code& e)
{
  if (!e)
  {
    //send data
  }
  else { //error occurs 
      closeSocket();

      boost::shared_ptr<DisConnectCommand> cmd(new DisConnectCommand());
      cmd->setClient(this->weak_from_this());  //here set this connection weak_ptr

      putCmd(cmd);  //do something in other thread.
  }  
}

core

, но когда множество клиентов подключается к серверу, ядро ​​сервера.Ядру нравится, что соединение было разорвано во время буксировки, память - ошибка.

bt вот так:

#0  0x00007f6e3aa561f7 in raise () from /lib64/libc.so.6
#1  0x00007f6e3aa578e8 in abort () from /lib64/libc.so.6
#2  0x00007f6e3b35c9d5 in __gnu_cxx::__verbose_terminate_handler() () from /lib64/libstdc++.so.6
#3  0x00007f6e3b35a946 in ?? () from /lib64/libstdc++.so.6
#4  0x00007f6e3b35a973 in std::terminate() () from /lib64/libstdc++.so.6
#5  0x00007f6e3b35ab93 in __cxa_throw () from /lib64/libstdc++.so.6
#6  0x00007f6e3b35b12d in operator new(unsigned long) () from /lib64/libstdc++.so.6
#7  0x00007f6e3b3b9c79 in std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) () from /lib64/libstdc++.so.6
#8  0x00007f6e3b3ba8bb in std::string::_Rep::_M_clone(std::allocator<char> const&, unsigned long) () from /lib64/libstdc++.so.6
#9  0x00007f6e3b3ba964 in std::string::reserve(unsigned long) () from /lib64/libstdc++.so.6
#10 0x00007f6e3b3baa28 in std::string::append(std::string const&) () from /lib64/libstdc++.so.6
#11 0x00007f6e3be5c4c8 in log4cxx::helpers::CharMessageBuffer::operator<< (this=0x7f6e20ff8750, msg=...) at messagebuffer.cpp:31
#12 0x00000000008a3a05 in ClientConnection::internalCloseSocket (this=0x7f6e046fefd0) at src/business/ClientConnection.cpp:216
#13 0x00000000008b620a in boost::_mfi::mf0<void, ClientConnection>::call<boost::shared_ptr<ClientConnection> > (this=0x7f6e20ff89c0, u=...)
    at externals/boost/include/boost/bind/mem_fn_template.hpp:40
#14 0x00000000008b5c79 in boost::_mfi::mf0<void, ClientConnection>::operator()<boost::shared_ptr<ClientConnection> > (this=0x7f6e20ff89c0, u=...)
    at externals/boost/include/boost/bind/mem_fn_template.hpp:55
#15 0x00000000008b5416 in boost::_bi::list1<boost::_bi::value<boost::shared_ptr<ClientConnection> > >::operator()<boost::_mfi::mf0<void, ClientConnection>, boost::_bi::list0> (
    this=0x7f6e20ff89d0, f=..., a=...) at externals/boost/include/boost/bind/bind.hpp:259
#16 0x00000000008b4997 in boost::_bi::bind_t<void, boost::_mfi::mf0<void, ClientConnection>, boost::_bi::list1<boost::_bi::value<boost::shared_ptr<ClientConnection> > > >::operator() (this=0x7f6e20ff89c0) at externals/boost/include/boost/bind/bind.hpp:1294
#17 0x00000000008b3667 in boost::asio::asio_handler_invoke<boost::_bi::bind_t<void, boost::_mfi::mf0<void, ClientConnection>, boost::_bi::list1<boost::_bi::value<boost::shared_ptr<ClientConnection> > > > > (function=...) at externals/boost/include/boost/asio/handler_invoke_hook.hpp:69
#18 0x00000000008b235a in boost_asio_handler_invoke_helpers::invoke<boost::_bi::bind_t<void, boost::_mfi::mf0<void, ClientConnection>, boost::_bi::list1<boost::_bi::value<boost::shared_ptr<ClientConnection> > > >, boost::_bi::bind_t<void, boost::_mfi::mf0<void, ClientConnection>, boost::_bi::list1<boost::_bi::value<boost::shared_ptr<ClientConnection> > > > > (
    function=..., context=...) at externals/boost/include/boost/asio/detail/handler_invoke_helpers.hpp:37
#19 0x00000000008b0ee3 in boost::asio::detail::completion_handler<boost::_bi::bind_t<void, boost::_mfi::mf0<void, ClientConnection>, boost::_bi::list1<boost::_bi::value<boost::shared_ptr<ClientConnection> > > > >::do_complete (owner=0x1a5a5c0, base=0x7f6e28018f30) at externals/boost/include/boost/asio/detail/completion_handler.hpp:68
#20 0x00000000007c3ef4 in boost::asio::detail::task_io_service_operation::complete (this=0x7f6e28018f30, owner=..., ec=..., bytes_transferred=0)
    at externals/boost/include/boost/asio/detail/task_io_service_operation.hpp:38
#21 0x00000000007c7937 in boost::asio::detail::strand_service::do_complete (owner=0x1a5a5c0, base=0x7f6df001ab40, ec=...) at externals/boost/include/boost/asio/detail/impl/strand_service.ipp:167
#22 0x00000000007c3ef4 in boost::asio::detail::task_io_service_operation::complete (this=0x7f6df001ab40, owner=..., ec=..., bytes_transferred=0)
    at externals/boost/include/boost/asio/detail/task_io_service_operation.hpp:38
#23 0x00000000007c5dde in boost::asio::detail::task_io_service::do_run_one (this=0x1a5a5c0, lock=..., this_thread=..., ec=...) at externals/boost/include/boost/asio/detail/impl/task_io_service.ipp:372
#24 0x00000000007c5845 in boost::asio::detail::task_io_service::run (this=0x1a5a5c0, ec=...) at externals/boost/include/boost/asio/detail/impl/task_io_service.ipp:149
#25 0x00000000007c60cf in boost::asio::io_service::run (this=0x1a54b10) at externals/boost/include/boost/asio/impl/io_service.ipp:59
#26 0x00000000008c27b6 in ProcessModule::threadRun (this=0x1a54b10) at src/business/ProcessModule.cpp:149
#27 0x00000000008c82e7 in boost::_mfi::mf0<void, ProcessModule>::operator() (this=0x1b0aee8, p=0x1a54b10) at externals/boost/include/boost/bind/mem_fn_template.hpp:49
#28 0x00000000008c824a in boost::_bi::list1<boost::_bi::value<ProcessModule*> >::operator()<boost::_mfi::mf0<void, ProcessModule>, boost::_bi::list0> (this=0x1b0aef8, 
    f=..., a=...) at externals/boost/include/boost/bind/bind.hpp:259
#29 0x00000000008c81f9 in boost::_bi::bind_t<void, boost::_mfi::mf0<void, ProcessModule>, boost::_bi::list1<boost::_bi::value<ProcessModule*> > >::operator() (
    this=0x1b0aee8) at externals/boost/include/boost/bind/bind.hpp:1294
#30 0x00000000008c811a in boost::detail::thread_data<boost::_bi::bind_t<void, boost::_mfi::mf0<void, ProcessModule>, boost::_bi::list1<boost::_bi::value<ProcessModule*> > > >::run (this=0x1b0ad30) at externals/boost/include/boost/thread/detail/thread.hpp:116

(gdb) p *this
$1 = {<boost::enable_shared_from_this<ClientConnection>> = {weak_this_ = {px = 0x7f981c4cf720, pn = {pi_ = 0x7f981c2feca0}}}, <boost::noncopyable_::noncopyable> = {<No data fields>}, 
  mIoService = @0x1333b10, 
  mSocket = {<boost::asio::basic_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> >> = {<boost::asio::basic_io_object<boost::asio::stream_socket_service<boost::asio::ip::tcp>, true>> = {implementation = {<boost::asio::detail::reactive_socket_service_base::base_implementation_type> = {socket_ = -1, state_ = 0 '\000', reactor_data_ = 0x0}, protocol_ = {family_ = 2}}, 
        service_ = 0x1371560}, <boost::asio::socket_base> = {static message_peek = 2, static message_out_of_band = 1, static message_do_not_route = 4, static message_end_of_record = 128, 
        static max_connections = 128}, <No data fields>}, <No data fields>}, mStrand = {service_ = @0x13e5510, impl_ = 0x7f98080500a0},

ClientConnection.cpp: 216 равно

  LOG_INFO("Close client[" << mClientId << "] socket connection");//line:216

mClientId неверное значение.похоже, этот класс уничтожен.

слабый ptr вроде:

(gdb) frame 12
(gdb) p *(weak_this_.pn.pi_)
$3 = {_vptr.sp_counted_base = 0x957710 <vtable for boost::detail::sp_counted_impl_p<ClientConnection>+16>, use_count_ = {_M_i = 3}, weak_count_ = {_M_i = 2}}

boost_asio / пример

У меня есть поиск в Интернете, найти https://www.boost.org/doc/libs/1_45_0/doc/html/boost_asio/example/http/server3/connection.cpp

в примере есть примечание, например:

int handle_read:

// If an error occurs then no new asynchronous operations are started. This
// means that all shared_ptr references to the connection object will
// disappear and the object will be destroyed automatically after this
// handler returns. The connection class's destructor closes the socket.

int handle_write:

// No new asynchronous operations are started. This means that all shared_ptr
// references to the connection object will disappear and the object will be
// destroyed automatically after this handler returns. The connection class's
// destructor closes the socket.

почему?

(i) Если в handle_read / handle_write возникает ошибка, не следует ли мне использовать это соединение weak_ptr в других потоках?
(ii) Жизненный цикл класса ClientConnection находится в Asio и контролируется Asio. Что не так в моем коде?

(iii) Я думаю, что он не может использовать stand.post () и connection_lable_ptr, чтобы что-то сделать.Нужно изменить код, как показано ниже?

void ClientConnection::handle_read(const boost::system::error_code& e,
    std::size_t bytes_transferred)
{
  if (!e)
  {
      //read data and use it
  }
  else { //error occurs 
      //closeSocket();
      //boost::shared_ptr<DisConnectCommand> cmd(new DisConnectCommand());
      //cmd->setClient(this->weak_from_this());  //here set this connection weak_ptr
      //putCmd(cmd);  //do something in other thread.


      //just close socket
      boost::system::error_code error;
      mSocket.close(error);
  }
}

Я в сети и жду вашей помощи.

спасибо.С наилучшими пожеланиями.

...