diff --git a/src/command/PlayerCommands.cxx b/src/command/PlayerCommands.cxx index a5705988a..995e3a22c 100644 --- a/src/command/PlayerCommands.cxx +++ b/src/command/PlayerCommands.cxx @@ -32,6 +32,7 @@ #include "AudioFormat.hxx" #include "ReplayGainConfig.hxx" #include "util/ScopeExit.hxx" +#include "util/Error.hxx" #ifdef ENABLE_DATABASE #include "db/update/Service.hxx" @@ -191,10 +192,15 @@ handle_status(Client &client, gcc_unused Request args, Response &r) } #endif - Error error = client.player_control.LockGetError(); - if (error.IsDefined()) - r.Format(COMMAND_STATUS_ERROR ": %s\n", - error.GetMessage()); + try { + client.player_control.LockCheckRethrowError(); + } catch (const std::exception &e) { + r.Format(COMMAND_STATUS_ERROR ": %s\n", e.what()); + } catch (const Error &error) { + r.Format(COMMAND_STATUS_ERROR ": %s\n", error.GetMessage()); + } catch (...) { + r.Format(COMMAND_STATUS_ERROR ": unknown\n"); + } song = playlist.GetNextPosition(); if (song >= 0) diff --git a/src/player/Control.cxx b/src/player/Control.cxx index e495c0d00..c61369c95 100644 --- a/src/player/Control.cxx +++ b/src/player/Control.cxx @@ -21,6 +21,7 @@ #include "Control.hxx" #include "Idle.hxx" #include "DetachedSong.hxx" +#include "util/Error.hxx" #include @@ -160,14 +161,23 @@ PlayerControl::LockGetStatus() return status; } +void +PlayerControl::SetError(PlayerError type, std::exception_ptr &&_error) +{ + assert(type != PlayerError::NONE); + assert(_error); + + error_type = type; + error = std::move(_error); +} + void PlayerControl::SetError(PlayerError type, Error &&_error) { assert(type != PlayerError::NONE); assert(_error.IsDefined()); - error_type = type; - error = std::move(_error); + SetError(type, std::make_exception_ptr(std::move(_error))); } void @@ -223,11 +233,11 @@ PlayerControl::SeekLocked(DetachedSong *song, SongTime t) assert(next_song == nullptr); if (error_type != PlayerError::NONE) { - assert(error.IsDefined()); - throw error; + assert(error); + std::rethrow_exception(error); } - assert(!error.IsDefined()); + assert(!error); } void diff --git a/src/player/Control.hxx b/src/player/Control.hxx index 1fda61ede..b0e985e91 100644 --- a/src/player/Control.hxx +++ b/src/player/Control.hxx @@ -24,12 +24,14 @@ #include "thread/Mutex.hxx" #include "thread/Cond.hxx" #include "thread/Thread.hxx" -#include "util/Error.hxx" #include "CrossFade.hxx" #include "Chrono.hxx" +#include + #include +class Error; class PlayerListener; class MultipleOutputs; class DetachedSong; @@ -135,7 +137,7 @@ struct PlayerControl { * #PlayerError::NONE. The object must be freed when this * object transitions back to #PlayerError::NONE. */ - Error error; + std::exception_ptr error; /** * A copy of the current #DetachedSong after its tags have @@ -327,7 +329,7 @@ private: void ClearError() { error_type = PlayerError::NONE; - error.Clear(); + error = std::exception_ptr(); } public: @@ -356,28 +358,25 @@ public: * @param error detailed error information; must be defined. */ void SetError(PlayerError type, Error &&error); + void SetError(PlayerError type, std::exception_ptr &&_error); /** - * Checks whether an error has occurred, and if so, returns a - * copy of the #Error object. + * Checks whether an error has occurred, and if so, rethrows + * it. * * Caller must lock the object. */ - gcc_pure - Error GetError() const { - Error result; + void CheckRethrowError() const { if (error_type != PlayerError::NONE) - result.Set(error); - return result; + std::rethrow_exception(error); } /** - * Like GetError(), but locks and unlocks the object. + * Like CheckRethrowError(), but locks and unlocks the object. */ - gcc_pure - Error LockGetError() const { + void LockCheckRethrowError() const { const ScopeLock protect(mutex); - return GetError(); + CheckRethrowError(); } void LockClearError();