better async exception handling

This commit is contained in:
badaix 2017-09-16 17:13:49 +02:00
parent 0ea51d95f3
commit 4670927d67
5 changed files with 30 additions and 18 deletions

View file

@ -22,7 +22,7 @@
#include "common/strCompat.h" #include "common/strCompat.h"
#include "common/snapException.h" #include "common/snapException.h"
#include "message/hello.h" #include "message/hello.h"
#include "common/log.h" #include "aixlog.hpp"
using namespace std; using namespace std;
@ -82,7 +82,7 @@ void ClientConnection::start()
// setsockopt(socket->native_handle(), SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); // setsockopt(socket->native_handle(), SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
socket_->connect(*iterator); socket_->connect(*iterator);
connected_ = true; connected_ = true;
SLOG(LOG_NOTICE) << "Connected to " << socket_->remote_endpoint().address().to_string() << endl; SLOG(NOTICE) << "Connected to " << socket_->remote_endpoint().address().to_string() << endl;
active_ = true; active_ = true;
readerThread_ = new thread(&ClientConnection::reader, this); readerThread_ = new thread(&ClientConnection::reader, this);
} }
@ -221,7 +221,7 @@ void ClientConnection::reader()
catch (const std::exception& e) catch (const std::exception& e)
{ {
if (messageReceiver_ != NULL) if (messageReceiver_ != NULL)
messageReceiver_->onException(this, e); messageReceiver_->onException(this, make_shared<SnapException>(e.what()));
} }
catch (...) catch (...)
{ {

View file

@ -48,12 +48,16 @@ struct PendingRequest
}; };
/// would be nicer to use std::exception_ptr
/// but not supported on all plattforms
typedef std::shared_ptr<std::exception> shared_exception_ptr;
/// Interface: callback for a received message and error reporting /// Interface: callback for a received message and error reporting
class MessageReceiver class MessageReceiver
{ {
public: public:
virtual void onMessageReceived(ClientConnection* connection, const msg::BaseMessage& baseMessage, char* buffer) = 0; virtual void onMessageReceived(ClientConnection* connection, const msg::BaseMessage& baseMessage, char* buffer) = 0;
virtual void onException(ClientConnection* connection, const std::exception& exception) = 0; virtual void onException(ClientConnection* connection, shared_exception_ptr exception) = 0;
}; };

View file

@ -29,7 +29,7 @@
#include "message/time.h" #include "message/time.h"
#include "message/hello.h" #include "message/hello.h"
#include "common/snapException.h" #include "common/snapException.h"
#include "common/log.h" #include "aixlog.hpp"
using namespace std; using namespace std;
@ -43,16 +43,15 @@ Controller::Controller(const std::string& hostId, size_t instance) : MessageRece
decoder_(nullptr), decoder_(nullptr),
player_(nullptr), player_(nullptr),
serverSettings_(nullptr), serverSettings_(nullptr),
asyncException_(false) async_exception_(nullptr)
{ {
} }
void Controller::onException(ClientConnection* connection, const std::exception& exception) void Controller::onException(ClientConnection* connection, shared_exception_ptr exception)
{ {
LOG(ERROR) << "Controller::onException: " << exception.what() << "\n"; LOG(ERROR) << "Controller::onException: " << exception->what() << "\n";
exception_ = exception.what(); async_exception_ = exception;
asyncException_ = true;
} }
@ -196,6 +195,12 @@ void Controller::worker()
msg::Time timeReq; msg::Time timeReq;
for (size_t n=0; n<50 && active_; ++n) for (size_t n=0; n<50 && active_; ++n)
{ {
if (async_exception_)
{
LOG(ERROR) << "Async exception: " << async_exception_->what() << "\n";
throw *async_exception_;
}
shared_ptr<msg::Time> reply = clientConnection_->sendReq<msg::Time>(&timeReq, chronos::msec(2000)); shared_ptr<msg::Time> reply = clientConnection_->sendReq<msg::Time>(&timeReq, chronos::msec(2000));
if (reply) if (reply)
{ {
@ -208,11 +213,15 @@ void Controller::worker()
/// Main loop /// Main loop
while (active_) while (active_)
{ {
LOG(DEBUG) << "Main loop\n";
for (size_t n=0; n<10 && active_; ++n) for (size_t n=0; n<10 && active_; ++n)
{ {
chronos::sleep(100); chronos::sleep(100);
if (asyncException_) if (async_exception_)
throw AsyncSnapException(exception_); {
LOG(ERROR) << "Async exception: " << async_exception_->what() << "\n";
throw *async_exception_;
}
} }
if (sendTimeSyncMessage(5000)) if (sendTimeSyncMessage(5000))
@ -221,8 +230,8 @@ void Controller::worker()
} }
catch (const std::exception& e) catch (const std::exception& e)
{ {
asyncException_ = false; async_exception_ = nullptr;
SLOG(LOG_ERR) << "Exception in Controller::worker(): " << e.what() << endl; SLOG(ERROR) << "Exception in Controller::worker(): " << e.what() << endl;
clientConnection_->stop(); clientConnection_->stop();
player_.reset(); player_.reset();
stream_.reset(); stream_.reset();

View file

@ -56,7 +56,7 @@ public:
/// Implementation of MessageReceiver. /// Implementation of MessageReceiver.
/// Used for async exception reporting /// Used for async exception reporting
virtual void onException(ClientConnection* connection, const std::exception& exception); virtual void onException(ClientConnection* connection, shared_exception_ptr exception);
private: private:
void worker(); void worker();
@ -76,8 +76,7 @@ private:
std::shared_ptr<msg::CodecHeader> headerChunk_; std::shared_ptr<msg::CodecHeader> headerChunk_;
std::mutex receiveMutex_; std::mutex receiveMutex_;
std::string exception_; shared_exception_ptr async_exception_;
bool asyncException_;
}; };

View file

@ -157,7 +157,7 @@ int main (int argc, char **argv)
AixLog::Log::init( AixLog::Log::init(
{ {
make_shared<AixLog::SinkCout>(debugSwitch.isSet()?(AixLog::Severity::trace):(AixLog::Severity::info), AixLog::Type::all, debugSwitch.isSet()?"%Y-%m-%d %H-%M-%S.#ms [#severity] (#tag)":"%Y-%m-%d %H-%M-%S [#severity]"), make_shared<AixLog::SinkCout>(debugSwitch.isSet()?(AixLog::Severity::trace):(AixLog::Severity::info), AixLog::Type::all, debugSwitch.isSet()?"%Y-%m-%d %H-%M-%S.#ms [#severity] (#function)":"%Y-%m-%d %H-%M-%S [#severity]"),
make_shared<AixLog::SinkNative>("snapclient", AixLog::Severity::trace, AixLog::Type::special) make_shared<AixLog::SinkNative>("snapclient", AixLog::Severity::trace, AixLog::Type::special)
} }
); );