Propagate exceptions from worker threads back to main thread
diff --git a/common/rfb/DecodeManager.cxx b/common/rfb/DecodeManager.cxx
index 724cf21..d6c3b0b 100644
--- a/common/rfb/DecodeManager.cxx
+++ b/common/rfb/DecodeManager.cxx
@@ -36,7 +36,7 @@
static LogWriter vlog("DecodeManager");
DecodeManager::DecodeManager(CConnection *conn) :
- conn(conn)
+ conn(conn), threadException(NULL)
{
size_t cpuCount;
@@ -71,6 +71,8 @@
threads.pop_back();
}
+ delete threadException;
+
while (!freeBuffers.empty()) {
delete freeBuffers.back();
freeBuffers.pop_back();
@@ -121,6 +123,9 @@
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 @@
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 @@
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 dec7a6c..fbb7f77 100644
--- a/common/rfb/DecodeManager.h
+++ b/common/rfb/DecodeManager.h
@@ -31,7 +31,10 @@
class Mutex;
}
-namespace rdr { class MemOutStream; }
+namespace rdr {
+ class Exception;
+ class MemOutStream;
+}
namespace rfb {
class CConnection;
@@ -50,6 +53,10 @@
void flush();
private:
+ void setThreadException(const rdr::Exception& e);
+ void throwThreadException();
+
+ private:
CConnection *conn;
Decoder *decoders[encodingMax+1];
@@ -90,6 +97,7 @@
};
std::list<DecodeThread*> threads;
+ rdr::Exception *threadException;
};
}