aboutsummaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorPierre Ossman <ossman@cendio.se>2025-03-13 19:03:53 +0100
committerPierre Ossman <ossman@cendio.se>2025-03-13 19:03:53 +0100
commit68e3cce0f8b11259b23f137aad7e366d5f4da081 (patch)
tree9b89e8e9cf59773a2c1901f4bade5320e4166cb6 /common
parente3987244cef69d404bf8ae3423a91fbf440f039d (diff)
downloadtigervnc-68e3cce0f8b11259b23f137aad7e366d5f4da081.tar.gz
tigervnc-68e3cce0f8b11259b23f137aad7e366d5f4da081.zip
Use std::exception_ptr to store exceptions
This is much more robust and flexible than what we came up with.
Diffstat (limited to 'common')
-rw-r--r--common/rdr/TLSInStream.cxx27
-rw-r--r--common/rdr/TLSInStream.h2
-rw-r--r--common/rdr/TLSOutStream.cxx27
-rw-r--r--common/rdr/TLSOutStream.h2
-rw-r--r--common/rfb/DecodeManager.cxx25
-rw-r--r--common/rfb/DecodeManager.h5
6 files changed, 36 insertions, 52 deletions
diff --git a/common/rdr/TLSInStream.cxx b/common/rdr/TLSInStream.cxx
index 9d9a33be..223e3ee6 100644
--- a/common/rdr/TLSInStream.cxx
+++ b/common/rdr/TLSInStream.cxx
@@ -42,7 +42,6 @@ ssize_t TLSInStream::pull(gnutls_transport_ptr_t str, void* data, size_t size)
InStream *in = self->in;
self->streamEmpty = false;
- delete self->saved_exception;
self->saved_exception = nullptr;
try {
@@ -58,15 +57,15 @@ ssize_t TLSInStream::pull(gnutls_transport_ptr_t str, void* data, size_t size)
in->readBytes((uint8_t*)data, size);
} catch (end_of_stream&) {
return 0;
- } catch (core::socket_error& e) {
- vlog.error("Failure reading TLS data: %s", e.what());
- gnutls_transport_set_errno(self->session, e.err);
- self->saved_exception = new core::socket_error(e);
- return -1;
} catch (std::exception& e) {
+ core::socket_error* se;
vlog.error("Failure reading TLS data: %s", e.what());
- gnutls_transport_set_errno(self->session, EINVAL);
- self->saved_exception = new std::runtime_error(e.what());
+ se = dynamic_cast<core::socket_error*>(&e);
+ if (se)
+ gnutls_transport_set_errno(self->session, se->err);
+ else
+ gnutls_transport_set_errno(self->session, EINVAL);
+ self->saved_exception = std::current_exception();
return -1;
}
@@ -74,7 +73,7 @@ ssize_t TLSInStream::pull(gnutls_transport_ptr_t str, void* data, size_t size)
}
TLSInStream::TLSInStream(InStream* _in, gnutls_session_t _session)
- : session(_session), in(_in), saved_exception(nullptr)
+ : session(_session), in(_in)
{
gnutls_transport_ptr_t recv, send;
@@ -86,8 +85,6 @@ TLSInStream::TLSInStream(InStream* _in, gnutls_session_t _session)
TLSInStream::~TLSInStream()
{
gnutls_transport_set_pull_function(session, nullptr);
-
- delete saved_exception;
}
bool TLSInStream::fillBuffer()
@@ -119,12 +116,8 @@ size_t TLSInStream::readTLS(uint8_t* buf, size_t len)
break;
};
- if (n == GNUTLS_E_PULL_ERROR) {
- if (dynamic_cast<core::socket_error*>(saved_exception))
- throw *dynamic_cast<core::socket_error*>(saved_exception);
- else
- throw std::runtime_error(saved_exception->what());
- }
+ if (n == GNUTLS_E_PULL_ERROR)
+ std::rethrow_exception(saved_exception);
if (n < 0)
throw tls_error("readTLS", n);
diff --git a/common/rdr/TLSInStream.h b/common/rdr/TLSInStream.h
index 2269b09d..bc9c74ba 100644
--- a/common/rdr/TLSInStream.h
+++ b/common/rdr/TLSInStream.h
@@ -41,7 +41,7 @@ namespace rdr {
InStream* in;
bool streamEmpty;
- std::exception* saved_exception;
+ std::exception_ptr saved_exception;
};
};
diff --git a/common/rdr/TLSOutStream.cxx b/common/rdr/TLSOutStream.cxx
index 5ea2b250..c3ae2d0a 100644
--- a/common/rdr/TLSOutStream.cxx
+++ b/common/rdr/TLSOutStream.cxx
@@ -42,21 +42,20 @@ ssize_t TLSOutStream::push(gnutls_transport_ptr_t str, const void* data,
TLSOutStream* self= (TLSOutStream*) str;
OutStream *out = self->out;
- delete self->saved_exception;
self->saved_exception = nullptr;
try {
out->writeBytes((const uint8_t*)data, size);
out->flush();
- } catch (core::socket_error& e) {
- vlog.error("Failure sending TLS data: %s", e.what());
- gnutls_transport_set_errno(self->session, e.err);
- self->saved_exception = new core::socket_error(e);
- return -1;
} catch (std::exception& e) {
+ core::socket_error* se;
vlog.error("Failure sending TLS data: %s", e.what());
- gnutls_transport_set_errno(self->session, EINVAL);
- self->saved_exception = new std::runtime_error(e.what());
+ se = dynamic_cast<core::socket_error*>(&e);
+ if (se)
+ gnutls_transport_set_errno(self->session, se->err);
+ else
+ gnutls_transport_set_errno(self->session, EINVAL);
+ self->saved_exception = std::current_exception();
return -1;
}
@@ -64,7 +63,7 @@ ssize_t TLSOutStream::push(gnutls_transport_ptr_t str, const void* data,
}
TLSOutStream::TLSOutStream(OutStream* _out, gnutls_session_t _session)
- : session(_session), out(_out), saved_exception(nullptr)
+ : session(_session), out(_out)
{
gnutls_transport_ptr_t recv, send;
@@ -82,8 +81,6 @@ TLSOutStream::~TLSOutStream()
}
#endif
gnutls_transport_set_push_function(session, nullptr);
-
- delete saved_exception;
}
void TLSOutStream::flush()
@@ -116,12 +113,8 @@ size_t TLSOutStream::writeTLS(const uint8_t* data, size_t length)
if (n == GNUTLS_E_INTERRUPTED || n == GNUTLS_E_AGAIN)
return 0;
- if (n == GNUTLS_E_PUSH_ERROR) {
- if (dynamic_cast<core::socket_error*>(saved_exception))
- throw *dynamic_cast<core::socket_error*>(saved_exception);
- else
- throw std::runtime_error(saved_exception->what());
- }
+ if (n == GNUTLS_E_PUSH_ERROR)
+ std::rethrow_exception(saved_exception);
if (n < 0)
throw tls_error("writeTLS", n);
diff --git a/common/rdr/TLSOutStream.h b/common/rdr/TLSOutStream.h
index 659f16f0..0ae9c460 100644
--- a/common/rdr/TLSOutStream.h
+++ b/common/rdr/TLSOutStream.h
@@ -42,7 +42,7 @@ namespace rdr {
gnutls_session_t session;
OutStream* out;
- std::exception* saved_exception;
+ std::exception_ptr saved_exception;
};
};
diff --git a/common/rfb/DecodeManager.cxx b/common/rfb/DecodeManager.cxx
index 97a90549..94908f86 100644
--- a/common/rfb/DecodeManager.cxx
+++ b/common/rfb/DecodeManager.cxx
@@ -85,8 +85,6 @@ DecodeManager::~DecodeManager()
threads.pop_back();
}
- delete threadException;
-
while (!freeBuffers.empty()) {
delete freeBuffers.back();
freeBuffers.pop_back();
@@ -242,30 +240,29 @@ void DecodeManager::logStats()
core::iecPrefix(bytes, "B").c_str(), ratio);
}
-void DecodeManager::setThreadException(const std::exception& e)
+void DecodeManager::setThreadException()
{
core::AutoMutex a(queueMutex);
- if (threadException != nullptr)
+ if (threadException)
return;
- threadException = new std::runtime_error(
- core::format("Exception on worker thread: %s", e.what()));
+ threadException = std::current_exception();
}
void DecodeManager::throwThreadException()
{
core::AutoMutex a(queueMutex);
- if (threadException == nullptr)
+ if (!threadException)
return;
- std::runtime_error e(threadException->what());
-
- delete threadException;
- threadException = nullptr;
-
- throw e;
+ try {
+ std::rethrow_exception(threadException);
+ } catch (...) {
+ threadException = nullptr;
+ throw;
+ }
}
DecodeManager::DecodeThread::DecodeThread(DecodeManager* manager_)
@@ -319,7 +316,7 @@ void DecodeManager::DecodeThread::worker()
entry->bufferStream->length(),
*entry->server, entry->pb);
} catch (std::exception& e) {
- manager->setThreadException(e);
+ manager->setThreadException();
} catch(...) {
assert(false);
}
diff --git a/common/rfb/DecodeManager.h b/common/rfb/DecodeManager.h
index a26f5fd6..95d3ceca 100644
--- a/common/rfb/DecodeManager.h
+++ b/common/rfb/DecodeManager.h
@@ -19,6 +19,7 @@
#ifndef __RFB_DECODEMANAGER_H__
#define __RFB_DECODEMANAGER_H__
+#include <exception>
#include <list>
#include <core/Region.h>
@@ -55,7 +56,7 @@ namespace rfb {
private:
void logStats();
- void setThreadException(const std::exception& e);
+ void setThreadException();
void throwThreadException();
private:
@@ -108,7 +109,7 @@ namespace rfb {
};
std::list<DecodeThread*> threads;
- std::exception *threadException;
+ std::exception_ptr threadException;
};
}