diff options
author | Pierre Ossman <ossman@cendio.se> | 2015-11-17 09:37:57 +0100 |
---|---|---|
committer | Pierre Ossman <ossman@cendio.se> | 2015-11-27 11:14:48 +0100 |
commit | 0560465250d352f21e85c94d80110502b1686a6d (patch) | |
tree | d95cbb26e2682b451588ef35846b63aef25fd1d1 /common | |
parent | 98d7af9cd15c0940aa12447ba324d90225afd4ca (diff) | |
download | tigervnc-0560465250d352f21e85c94d80110502b1686a6d.tar.gz tigervnc-0560465250d352f21e85c94d80110502b1686a6d.zip |
Propagate exceptions from worker threads back to main thread
Diffstat (limited to 'common')
-rw-r--r-- | common/rfb/DecodeManager.cxx | 37 | ||||
-rw-r--r-- | common/rfb/DecodeManager.h | 10 |
2 files changed, 44 insertions, 3 deletions
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; @@ -50,6 +53,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<DecodeThread*> threads; + rdr::Exception *threadException; }; } |