static LogWriter vlog("DecodeManager");
DecodeManager::DecodeManager(CConnection *conn) :
- conn(conn)
+ conn(conn), threadException(NULL)
{
size_t cpuCount;
threads.pop_back();
}
+ delete threadException;
+
while (!freeBuffers.empty()) {
delete freeBuffers.back();
freeBuffers.pop_back();
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);
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)
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);
}
class Mutex;
}
-namespace rdr { class MemOutStream; }
+namespace rdr {
+ class Exception;
+ class MemOutStream;
+}
namespace rfb {
class CConnection;
void flush();
+ private:
+ void setThreadException(const rdr::Exception& e);
+ void throwThreadException();
+
private:
CConnection *conn;
Decoder *decoders[encodingMax+1];
};
std::list<DecodeThread*> threads;
+ rdr::Exception *threadException;
};
}