]> source.dussan.org Git - tigervnc.git/commitdiff
Propagate exceptions from worker threads back to main thread
authorPierre Ossman <ossman@cendio.se>
Tue, 17 Nov 2015 08:37:57 +0000 (09:37 +0100)
committerPierre Ossman <ossman@cendio.se>
Fri, 27 Nov 2015 10:14:48 +0000 (11:14 +0100)
common/rfb/DecodeManager.cxx
common/rfb/DecodeManager.h

index 724cf215a474aa750b22afaa249a03aac7bd1cc1..d6c3b0b58fb331cd677231512cabfbccc08f3ca1 100644 (file)
@@ -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);
     }
 
index dec7a6cbf351ceeb7574579becfde176c480fd52..fbb7f77cd4ad9e713f8fee0d2e09f37cbaefde51 100644 (file)
@@ -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<DecodeThread*> threads;
+    rdr::Exception *threadException;
   };
 }