Search code examples
c++boostwt

Wt::Http::Client always end with throw_exception<boost::bad_weak_ptr>()


I am currently doing modifications to an existing program written in C++11 with Wt and boost. One problem still remains, I always get exception when posting data using the Wt::Http::Client.

Here is the current code :

Communication.h

#ifndef COMMUNICATION_H_
#define COMMUNICATION_H_

#include <Wt/WResource>
#include <Wt/Http/Client>
#include <Wt/Http/Message>

class Communication
{
    public:
        static bool sendData(std::string p_sData);
        static void handleHTTPResponse(boost::system::error_code err, const Wt::Http::Message& response);

    private:
        Communication();
        ~Communication();
};

#endif /* COMMUNICATION_H_ */

Communication.cpp

#include "Communication.h"
#include <Wt/WDateTime>
#include "DemtroysUtilitaires.h"

Communication::Communication()
{

}

Communication::~Communication()
{

}

bool Communication::sendData(std::string p_sData)
{
    Wt::Http::Client requete;
    Wt::Http::Message message;
    bool bResult = false;

    std::cout << "NETWORK >>> " << p_sData << std::endl;

    message.addHeader("Content-type","application/json");
    message.addBodyText(p_sData);
    requete.done().connect(boost::bind(&Communication::handleHTTPResponse,_1,_2));

    if(requete.post("http://someserver.com",message))
    {
        bResult = true;
    }

    return bResult;
}

void Communication::handleHTTPResponse(boost::system::error_code err, const Wt::Http::Message& response)
{
    std::cout << "********************************************************************************" << std::endl;
    std::cout << "Communication::handleHttpResponse() status : " << response.status() << std::endl;
    if(err || response.status() != 200)
    {
        std::cerr << "Error: " << err.message() << ", " << response.status() << std::endl;
    }
    std::cout << "********************************************************************************" << std::endl;
}

Here is the stack trace :

Thread [15] 28055 [core: 3] (Suspended : Signal : SIGABRT:Aborted)  
    __GI_raise() at raise.c:56 0x7ffff5914cc9   
    __GI_abort() at abort.c:89 0x7ffff59180d8   
    __gnu_cxx::__verbose_terminate_handler() at 0x7ffff5f196b5  
    0x7ffff5f17836  
    std::terminate() at 0x7ffff5f17863  
    __cxa_throw() at 0x7ffff5f17aa2 
    throw_exception<boost::bad_weak_ptr>() at throw_exception.hpp:70 0x7ffff767682c 
    boost::detail::shared_count::shared_count() at shared_count.hpp:580 0x7ffff767682c  
    shared_ptr<Wt::Http::Client::Impl>() at shared_ptr.hpp:404 0x7ffff79201b8   
    shared_from_this() at enable_shared_from_this.hpp:49 0x7ffff79201b8 
    Wt::Http::Client::Impl::startTimer() at Client.C:143 0x7ffff79201b8 
    Wt::Http::Client::Impl::handleResolve() at Client.C:173 0x7ffff7925d2d  
    operator() at mem_fn_template.hpp:280 0x7ffff7924afc    
    operator()<boost::_mfi::mf2<void, Wt::Http::Client::Impl, const boost::system::error_code&, boost::asio::ip::basic_resolver_iterator<boost::asio::ip::tcp> >, boost::_bi::list2<const boost::system::error_code&, const boost::asio::ip::basic_resolver_iterator<boost::asio::ip::tcp>&> > at bind.hpp:392 0x7ffff7924afc   
    operator()<boost::system::error_code, boost::asio::ip::basic_resolver_iterator<boost::asio::ip::tcp> > at bind_template.hpp:102 0x7ffff7924afc  
    operator() at bind_handler.hpp:127 0x7ffff7924afc   
    asio_handler_invoke<boost::asio::detail::binder2<boost::_bi::bind_t<void, boost::_mfi::mf2<void, Wt::Http::Client::Impl, boost::system::error_code const&, boost::asio::ip::basic_resolver_iterator<boost::asio::ip::tcp> >, boost::_bi::list3<boost::_bi::value<Wt::Http::Client::Impl*>, boost::arg<1> (*)(), boost::arg<2> (*)()> >, boost::system::error_code, boost::asio::ip::basic_resolver_iterator<boost::asio::ip::tcp> > > at handler_invoke_hook.hpp:69 0x7ffff7924afc  
    invoke<boost::asio::detail::binder2<boost::_bi::bind_t<void, boost::_mfi::mf2<void, Wt::Http::Client::Impl, boost::system::error_code const&, boost::asio::ip::basic_resolver_iterator<boost::asio::ip::tcp> >, boost::_bi::list3<boost::_bi::value<Wt::Http::Client::Impl*>, boost::arg<1> (*)(), boost::arg<2> (*)()> >, boost::system::error_code, boost::asio::ip::basic_resolver_iterator<boost::asio::ip::tcp> >, boost::_bi::bind_t<void, boost::_mfi::mf2<void, Wt::Http::Client::Impl, boost::system::error_code const&, boost::asio::ip::basic_resolver_iterator<boost::asio::ip::tcp> >, boost::_bi::list3<boost::_bi::value<Wt::Http::Client::Impl*>, boost::arg<1> (*)(), boost::arg<2> (*)()> > > at handler_invoke_helpers.hpp:37 0x7ffff7924afc 
    boost::asio::detail::resolve_op<boost::asio::ip::tcp, boost::_bi::bind_t<void, boost::_mfi::mf2<void, Wt::Http::Client::Impl, boost::system::error_code const&, boost::asio::ip::basic_resolver_iterator<boost::asio::ip::tcp> >, boost::_bi::list3<boost::_bi::value<Wt::Http::Client::Impl*>, boost::arg<1> (*)(), boost::arg<2> (*)()> > >::do_complete at resolve_op.hpp:112 0x7ffff7924afc 
    complete() at task_io_service_operation.hpp:38 0x7ffff773cfef   
    do_run_one() at task_io_service.ipp:384 0x7ffff773cfef  
    boost::asio::detail::task_io_service::run() at task_io_service.ipp:153 0x7ffff773cfef   
    run() at io_service.ipp:59 0x7ffff773914c   
    Wt::WIOService::run() at WIOService.C:180 0x7ffff773914c    
    0x7ffff6bb8e7a  
    start_thread() at pthread_create.c:312 0x7ffff4da4182   
    clone() at clone.S:111 0x7ffff59d847d

By analysing the stack trace, I'm pretty sure this is related with the done() method from the Wt::Http::Client that is not implemented properly, but can't figure out why!


Solution

  • My opinion that the problem is that the Client class instance requete is declared as a local variable. Also the call requete.post(...) is asynchronous, i.e. it saves a request to an internal queue of Wt and finishes immediately without waiting till the message is delivered. Thus the Communication::sendData method finishes before the Wt internal code processes the queue. When Wt processes the queue the instance requete is already destroyed. Due to this fact the code inside of Wt::Http::Client::Impl::startTimer() cannot get a pointer and throws the exception.