mirror of
https://github.com/badaix/snapcast.git
synced 2025-05-16 18:46:15 +02:00
better async exception handling
This commit is contained in:
parent
0ea51d95f3
commit
4670927d67
5 changed files with 30 additions and 18 deletions
|
@ -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 (...)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue