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!
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.