From c20aefc10fed618ce5c083e885be2d7c3c89cafd Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Mon, 16 Apr 2018 17:04:55 -0400 Subject: [PATCH] Save, later rethrow exceptions caught in callbacks from C libraries --- src/effects/SBSMSEffect.cpp | 30 ++++++++++-------------------- src/effects/nyquist/Nyquist.cpp | 27 +++++++++------------------ src/effects/nyquist/Nyquist.h | 3 +-- 3 files changed, 20 insertions(+), 40 deletions(-) diff --git a/src/effects/SBSMSEffect.cpp b/src/effects/SBSMSEffect.cpp index eb7336d49..6e1c3f895 100644 --- a/src/effects/SBSMSEffect.cpp +++ b/src/effects/SBSMSEffect.cpp @@ -62,8 +62,7 @@ public: std::unique_ptr outputLeftTrack; std::unique_ptr outputRightTrack; - wxFileName failedFileName; - bool error{ false }; + std::exception_ptr mpException {}; }; class SBSMSEffectInterface final : public SBSMSInterfaceSliding { @@ -100,23 +99,16 @@ long resampleCB(void *cb_data, SBSMSFrame *data) // I don't know if we can safely propagate errors through sbsms, and it // does not seem to let us report error codes, so use this roundabout to // stop the effect early. - // This would be easier with std::exception_ptr but we don't have that yet. try { r->leftTrack->Get( (samplePtr)(r->leftBuffer.get()), floatSample, r->offset, blockSize); r->rightTrack->Get( (samplePtr)(r->rightBuffer.get()), floatSample, r->offset, blockSize); } - catch ( const FileException& e ) { - if ( e.cause == FileException::Cause::Read ) - r->failedFileName = e.fileName; - data->size = 0; - r->error = true; - return 0; - } catch ( ... ) { + // Save the exception object for re-throw when out of the library + r->mpException = std::current_exception(); data->size = 0; - r->error = true; return 0; } @@ -425,15 +417,13 @@ bool EffectSBSMS::Process() if (TrackProgress(nWhichTrack, frac)) return false; } - if (rb.failedFileName.IsOk()) - // re-construct an exception - // I wish I had std::exception_ptr instead - // and could re-throw any AudacityException - throw FileException{ - FileException::Cause::Read, rb.failedFileName }; - else if (rb.error) - // well, what? - bGoodResult = false; + + { + auto pException = rb.mpException; + rb.mpException = {}; + if (pException) + std::rethrow_exception(pException); + } if (bGoodResult) { rb.outputLeftTrack->Flush(); diff --git a/src/effects/nyquist/Nyquist.cpp b/src/effects/nyquist/Nyquist.cpp index ed522765b..1e3eddb03 100644 --- a/src/effects/nyquist/Nyquist.cpp +++ b/src/effects/nyquist/Nyquist.cpp @@ -967,8 +967,7 @@ bool NyquistEffect::TransferDataFromWindow() bool NyquistEffect::ProcessOne() { - mError = false; - mFailedFileName.Clear(); + mpException = {}; nyx_rval rval; @@ -1393,15 +1392,12 @@ bool NyquistEffect::ProcessOne() } // See if GetCallback found read errors - if (mFailedFileName.IsOk()) - // re-construct an exception - // I wish I had std::exception_ptr instead - // and could re-throw any AudacityException - throw FileException{ - FileException::Cause::Read, mFailedFileName }; - else if (mError) - // what, then? - success = false; + { + auto pException = mpException; + mpException = {}; + if (pException) + std::rethrow_exception( pException ); + } if (!success) return false; @@ -2156,14 +2152,9 @@ int NyquistEffect::GetCallback(float *buffer, int ch, mCurBuffer[ch].ptr(), floatSample, mCurBufferStart[ch], mCurBufferLen[ch]); } - catch ( const FileException& e ) { - if ( e.cause == FileException::Cause::Read ) - mFailedFileName = e.fileName; - mError = true; - return -1; - } catch ( ... ) { - mError = true; + // Save the exception object for re-throw when out of the library + mpException = std::current_exception(); return -1; } } diff --git a/src/effects/nyquist/Nyquist.h b/src/effects/nyquist/Nyquist.h index da215f033..beaefe97a 100644 --- a/src/effects/nyquist/Nyquist.h +++ b/src/effects/nyquist/Nyquist.h @@ -275,8 +275,7 @@ private: wxTextCtrl *mCommandText; wxCheckBox *mVersionCheckBox; - bool mError{ false }; - wxFileName mFailedFileName; + std::exception_ptr mpException {}; DECLARE_EVENT_TABLE()