summaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2015-11-17 09:37:57 +0100
committerPierre Ossman <ossman@cendio.se>2015-11-27 11:14:48 +0100
commit0560465250d352f21e85c94d80110502b1686a6d (patch)
treed95cbb26e2682b451588ef35846b63aef25fd1d1 /common
parent98d7af9cd15c0940aa12447ba324d90225afd4ca (diff)
downloadtigervnc-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.cxx37
-rw-r--r--common/rfb/DecodeManager.h10
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;
};
}