diff options
author | Pierre Ossman <ossman@cendio.se> | 2025-03-13 19:03:53 +0100 |
---|---|---|
committer | Pierre Ossman <ossman@cendio.se> | 2025-03-13 19:03:53 +0100 |
commit | 68e3cce0f8b11259b23f137aad7e366d5f4da081 (patch) | |
tree | 9b89e8e9cf59773a2c1901f4bade5320e4166cb6 /common | |
parent | e3987244cef69d404bf8ae3423a91fbf440f039d (diff) | |
download | tigervnc-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.cxx | 27 | ||||
-rw-r--r-- | common/rdr/TLSInStream.h | 2 | ||||
-rw-r--r-- | common/rdr/TLSOutStream.cxx | 27 | ||||
-rw-r--r-- | common/rdr/TLSOutStream.h | 2 | ||||
-rw-r--r-- | common/rfb/DecodeManager.cxx | 25 | ||||
-rw-r--r-- | common/rfb/DecodeManager.h | 5 |
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; }; } |