1

我正在编写一个 UDP 客户端。该协议被编写为单个请求的单个响应。我有一个发送消息的事务类,然后运行一个计时器来等待响应。如果在预期时间内收到响应,则停止计时器并调用成功回调。否则调用失败回调。最后,在这两种情况下都会无条件地调用完成回调。

template <typename RequestType, typename ResponseType>
struct transaction{
    boost::asio::io_service&                _service;
    boost::asio::deadline_timer             _timer;
    typename ResponseType::buffer_type      _buff;
    RequestType                             _request;

    transaction(boost::asio::io_service& service, const RequestType& req): _service(service), _timer(service), _request(req){}
    virtual ~transaction(){}
    template <typename SuccessCallback, typename FailureCallback, typename FinishCallback>
    void exec(boost::asio::ip::udp::endpoint& endpoint, boost::asio::ip::udp::socket& socket, unsigned wait_seconds, SuccessCallback success, FailureCallback failure, FinishCallback finish){
        _timer.expires_from_now(boost::posix_time::seconds(wait_seconds));
        _timer.async_wait([this, &failure, &finish](const boost::system::error_code& error){
            if(!error){
                std::cout << "failed to receive reply within deadline" << std::endl;
                failure(_request);
                finish(this);
            }
        });
        socket.async_receive_from(boost::asio::buffer(_buff), endpoint, [this, &success, finish](const boost::system::error_code& error, std::size_t bytes_transferred){
            if(!error && bytes_transferred > 0){
                ResponseType reply;
                reply.parse(_buff);
                _timer.cancel();
                success(reply);
                finish(this);
            }
        });
        socket.send_to(boost::asio::buffer(_request.buffer()), endpoint);
    }
};

交易一次正常。但是,如果失败,我想重试。以下是第一次正常工作的敲门功能。但在失败回调中,它再次调用敲门,导致段错误。

typedef transaction<request_knock, reply_knock> transaction_knock;
void knock(boost::asio::io_service& service, boost::asio::ip::udp::endpoint& endpoint, boost::asio::ip::udp::socket& socket){
    request_knock knock_request(0);
    transaction_knock* knock_transaction = new transaction_knock(service, knock_request);
    knock_transaction->exec(endpoint, socket, 5, [](const reply_knock& reply){
        std::cout << "success " << reply._data.id << std::endl;
    }, [&service, &endpoint, &socket](const request_knock& req){
        // FAILURE
        knock(service, endpoint, socket);
    }, [](transaction_knock* transaction){
        delete transaction;
    });
}

以下是回溯

#0  0x00007ffff7f0f244 in pthread_mutex_lock () from /usr/lib/libpthread.so.0
#1  0x000055555559f3c8 in boost::asio::detail::posix_mutex::lock (this=0xfbad2a8c) at /usr/include/boost/asio/detail/posix_mutex.hpp:52
#2  0x00005555555a7cb4 in boost::asio::detail::scoped_lock<boost::asio::detail::posix_mutex>::scoped_lock (this=0x7fffffffe2a0, m=...)
    at /usr/include/boost/asio/detail/scoped_lock.hpp:46
#3  0x00005555555a02f5 in boost::asio::detail::service_registry::do_use_service (this=0xfbad2a84, key=..., 
    factory=0x5555555b4666 <boost::asio::detail::service_registry::create<boost::asio::detail::deadline_timer_service<boost::asio::time_traits<boost::posix_time::ptime> >, boost::asio::io_context>(void*)>, owner=0x7ffff7bbe5c0 <_IO_2_1_stdout_>)
    at /usr/include/boost/asio/detail/impl/service_registry.ipp:117
#4  0x00005555555b39da in boost::asio::detail::service_registry::use_service<boost::asio::detail::deadline_timer_service<boost::asio::time_traits<boost::posix_time::ptime> > > (this=0xfbad2a84, owner=...) at /usr/include/boost/asio/detail/impl/service_registry.hpp:39
#5  0x00005555555b2219 in boost::asio::use_service<boost::asio::detail::deadline_timer_service<boost::asio::time_traits<boost::posix_time::ptime> > > (ioc=...) at /usr/include/boost/asio/impl/io_context.hpp:39
#6  0x00005555555b021d in boost::asio::basic_io_object<boost::asio::detail::deadline_timer_service<boost::asio::time_traits<boost::posix_time::ptime> >, true>::basic_io_object (this=0x5555555e2f20, io_context=...) at /usr/include/boost/asio/basic_io_object.hpp:224
#7  0x00005555555ad795 in boost::asio::basic_deadline_timer<boost::posix_time::ptime, boost::asio::time_traits<boost::posix_time::ptime> >::basic_deadline_timer (this=0x5555555e2f20, io_context=...) at /usr/include/boost/asio/basic_deadline_timer.hpp:159
#8  0x00005555555aa4ab in transaction<request_knock, reply_knock>::transaction (this=0x5555555e2f10, service=..., req=...)
    at /home/else/Projects/comet/main.cpp:111
#9  0x000055555559a90c in knock (service=..., endpoint=..., socket=...) at /home/else/Projects/comet/main.cpp:192
#10 0x000055555559a8a2 in <lambda(const request_knock&)>::operator()(const request_knock &) const (__closure=0x7fffffffe3d0, req=...)

我想弄清楚这次崩溃的原因是什么?

4

0 回答 0