SIGSEGV при втором вызове boost :: asio :: udp socket :: async_recv при работающем boost :: thread - PullRequest
0 голосов
/ 02 апреля 2019

Я получаю SIGSEGV в следующем классе во второй раз, когда я вызываю start_receive (). Он работает правильно в моей функции open (), но, похоже, не работает, когда ввод получен, и я пытаюсь перезапустить прослушивание для получения дополнительной информации:

#0  0x0000555555584154 in boost::asio::basic_io_object<boost::asio::datagram_socket_service<boost::asio::ip::udp>, true>::get_service (this=0x100007f00000000)
    at /usr/include/boost/asio/basic_io_object.hpp:225
#1  0x000055555558398b in boost::asio::basic_datagram_socket<boost::asio::ip::udp, boost::asio::datagram_socket_service<boost::asio::ip::udp> >::async_receive_from<boost::asio::mutable_buffers_1, boost::_bi::bind_t<int, boost::_mfi::mf2<int, Vast::net_udpNC_MChandler, boost::system::error_code const&, unsigned long>, boost::_bi::list3<boost::_bi::value<Vast::net_udpNC_MChandler*>, boost::arg<1> (*)(), boost::arg<2> (*)()> > > (this=0x100007f00000000, buffers=..., 
    sender_endpoint=..., handler=...)
    at /usr/include/boost/asio/basic_datagram_socket.hpp:895
#2  0x000055555557a889 in Vast::net_udpNC_MChandler::start_receive (
    this=0x7fffffff5c70) at net_udpnc_mchandler.cpp:58
#3  0x000055555557aa77 in Vast::net_udpNC_MChandler::handle_input (
    this=0x7fffffff5c70, error=..., bytes_transferred=24)
    at net_udpnc_mchandler.cpp:100
#4  0x000055555557abb3 in Vast::net_udpNC_MChandler::handle_buffer (
    this=0x7fffffff5c70, buf=0x7fffffffdad0 "\035\300", bytes_transferred=24)
    at net_udpnc_mchandler.cpp:114
#5  0x000055555556397f in test_process_encoded ()
    at unittest_net_udpnc_mchandler.cpp:43
#6  0x000055555556400e in main () at unittest_net_udpnc_mchandler.cpp:101

Заголовок:

class net_udpNC_MChandler
    {
    public:
        net_udpNC_MChandler(ip::udp::endpoint local_endpoint);

        //MChandler will run its own io_service
        int open (AbstractRLNCMsgReceiver *msghandler);

        int handle_buffer (char *buf, std::size_t bytes_transferred);

    protected:

        //Start the receiving loop
        void start_receive ();

        // handling incoming message
        int handle_input (const boost::system::error_code& error,
                          std::size_t bytes_transferred);

    private:
        ip::udp::socket             *_udp;
        ip::udp::endpoint           _remote_endpoint_;
        ip::udp::endpoint           _local_endpoint;
        ip::udp::endpoint           MC_address;
        char                        _buf[VAST_BUFSIZ];
        AbstractRLNCMsgReceiver     *_msghandler = NULL;

        io_service                  *_io_service;
        boost::thread               *_iosthread;

};

Исходный файл:

net_udpNC_MChandler::net_udpNC_MChandler(ip::udp::endpoint local_endpoint) :
        MC_address(ip::address::from_string("239.255.0.1"), 1037)
    {
        _io_service = new io_service();
        _local_endpoint = local_endpoint;
    }

    int net_udpNC_MChandler::open(AbstractRLNCMsgReceiver *msghandler) {
        _msghandler = msghandler;

        if (_udp == NULL) {
            _udp = new ip::udp::socket(*_io_service);
            _udp->open(ip::udp::v4());
            _udp->set_option(ip::udp::socket::reuse_address(true));
            _udp->set_option(ip::multicast::join_group(MC_address.address ()));

            boost::system::error_code ec;

            _udp->bind(MC_address, ec);

            std::cout << "net_udpnc_mchandler::open " + ec.message() << std::endl;

            if (ec)
            {
                std::cout << "net_udpnc_mchandler:: open MC address failed" << ec.message() << std::endl;
            }

            //Add async receive to io_service queue
            start_receive();

            std::cout << "net_udpnc_mchandler::open _udp->_local_endpoint: " << _udp->local_endpoint() << " _local_endpoint" << _local_endpoint << std::endl;

            //Start the thread handling async receives
            _iosthread = new boost::thread(boost::bind(&boost::asio::io_service::run, _io_service));
        }

        return 0;
    }

    void net_udpNC_MChandler::start_receive()
    {
        _udp->async_receive_from(
            boost::asio::buffer(_buf, VAST_BUFSIZ), _remote_endpoint_,
            boost::bind(&net_udpNC_MChandler::handle_input, this,
              boost::asio::placeholders::error,
              boost::asio::placeholders::bytes_transferred));
    }

    // handling incoming message
    int net_udpNC_MChandler::handle_input (const boost::system::error_code& error,
          std::size_t bytes_transferred)
    {

        RLNCHeader header;

        if (!error)
        {
            //Store UDP messages

            char *p = _buf;

            memcpy(&header, p, sizeof(RLNCHeader));


            if (RLNCHeader_factory::isRLNCHeader (header) && header.enc_packet_count > 1)
                {
                    CPPDEBUG("net_udpnc_mchandler::handle_input: Encoded packet received" << std::endl);
                    process_encoded (bytes_transferred);
                }

            //Restart waiting for new packets
            start_receive();
        }
        else {
            CPPDEBUG("Error on UDP socket receive: " << error.message() << std::endl;);
        }
        return -1;
    }

Самое странное, что все работает, если я использую конструктор по умолчанию без аргументов (т.е. без local_endpoint), этот SIGSEGV не появляется. Но как только я меняю конструктор на текущий, я получаю SIGSEGV.

_io_service - это объект класса, и он не разрушается нигде, кроме деструктора, поэтому я не знаю, как получить SIGSEGV для него ...

Есть ли какое-то требование к классу обработчика, чтобы у него был конструктор без аргументов?

...