From: Pierre Ossman Date: Tue, 17 Nov 2015 08:37:57 +0000 (+0100) Subject: Propagate exceptions from worker threads back to main thread X-Git-Tag: v1.6.90~95^2~5 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=0560465250d352f21e85c94d80110502b1686a6d;p=tigervnc.git Propagate exceptions from worker threads back to main thread --- diff --git a/common/rfb/DecodeManager.cxx b/common/rfb/DecodeManager.cxx index 724cf215..d6c3b0b5 100644 --- a/common/rfb/DecodeManager.cxx +++ b/common/rfb/DecodeManager.cxx @@ -36,7 +36,7 @@ using namespace rfb; static LogWriter vlog("DecodeManager"); DecodeManager::DecodeManager(CConnection *conn) : - conn(conn) + conn(conn), threadException(NULL) { size_t cpuCount; @@ -71,6 +71,8 @@ DecodeManager::~DecodeManager() threads.pop_back(); } + delete threadException; + while (!freeBuffers.empty()) { delete freeBuffers.back(); freeBuffers.pop_back(); @@ -121,6 +123,9 @@ void DecodeManager::decodeRect(const Rect& r, int encoding, queueMutex->unlock(); + // First check if any thread has encountered a problem + throwThreadException(); + // Read the rect bufferStream->clear(); decoder->readRect(r, conn->getInStream(), conn->cp, bufferStream); @@ -163,6 +168,33 @@ void DecodeManager::flush() producerCond->wait(); queueMutex->unlock(); + + throwThreadException(); +} + +void DecodeManager::setThreadException(const rdr::Exception& e) +{ + os::AutoMutex a(queueMutex); + + if (threadException == NULL) + return; + + threadException = new rdr::Exception("Exception on worker thread: %s", e.str()); +} + +void DecodeManager::throwThreadException() +{ + os::AutoMutex a(queueMutex); + + if (threadException == NULL) + return; + + rdr::Exception e(*threadException); + + delete threadException; + threadException = NULL; + + throw e; } DecodeManager::DecodeThread::DecodeThread(DecodeManager* manager) @@ -218,8 +250,9 @@ void DecodeManager::DecodeThread::worker() entry->decoder->decodeRect(entry->rect, entry->bufferStream->data(), entry->bufferStream->length(), *entry->cp, entry->pb); + } catch (rdr::Exception e) { + manager->setThreadException(e); } catch(...) { - // FIXME: Try to get the exception back to the main thread assert(false); } diff --git a/common/rfb/DecodeManager.h b/common/rfb/DecodeManager.h index dec7a6cb..fbb7f77c 100644 --- a/common/rfb/DecodeManager.h +++ b/common/rfb/DecodeManager.h @@ -31,7 +31,10 @@ namespace os { class Mutex; } -namespace rdr { class MemOutStream; } +namespace rdr { + class Exception; + class MemOutStream; +} namespace rfb { class CConnection; @@ -49,6 +52,10 @@ namespace rfb { void flush(); + private: + void setThreadException(const rdr::Exception& e); + void throwThreadException(); + private: CConnection *conn; Decoder *decoders[encodingMax+1]; @@ -90,6 +97,7 @@ namespace rfb { }; std::list threads; + rdr::Exception *threadException; }; }