diff --git a/src/evhelper.cpp b/src/evhelper.cpp index 101c955..f7a19ac 100644 --- a/src/evhelper.cpp +++ b/src/evhelper.cpp @@ -138,7 +138,7 @@ struct evbase::Pvt : public epicsThreadRunable epicsThreadGetStackSize(epicsThreadStackBig), prio) { - epicsThreadOnce(&evthread_once, &evthread_init, nullptr); + threadOnce(&evthread_once, &evthread_init, nullptr); worker.start(); start_sync.wait(); diff --git a/src/log.cpp b/src/log.cpp index a542d43..9645b76 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -243,7 +243,7 @@ Level logger::init() if(this->lvl.compare_exchange_strong(lvl, Level::Warn)) { // logger now has default config of Level::Err // we will fully initialize - epicsThreadOnce(&logger_once, &logger_prepare, nullptr); + threadOnce(&logger_once, &logger_prepare, nullptr); assert(logger_gbl); Guard G(logger_gbl->lock); @@ -295,7 +295,7 @@ void xerrlogHexPrintf(const void *buf, size_t buflen) void logger_level_set(const char *name, int lvl) { - epicsThreadOnce(&logger_once, &logger_prepare, nullptr); + threadOnce(&logger_once, &logger_prepare, nullptr); assert(logger_gbl); Guard G(logger_gbl->lock); @@ -304,7 +304,7 @@ void logger_level_set(const char *name, int lvl) void logger_level_clear() { - epicsThreadOnce(&logger_once, &logger_prepare, nullptr); + threadOnce(&logger_once, &logger_prepare, nullptr); assert(logger_gbl); Guard G(logger_gbl->lock); @@ -317,7 +317,7 @@ void logger_config_env() if(!env || !*env) return; - epicsThreadOnce(&logger_once, &logger_prepare, nullptr); + threadOnce(&logger_once, &logger_prepare, nullptr); Guard G(logger_gbl->lock); @@ -366,7 +366,7 @@ namespace pvxs {namespace impl { void logger_shutdown() { - epicsThreadOnce(&logger_once, &logger_prepare, nullptr); + threadOnce(&logger_once, &logger_prepare, nullptr); errlogFlush(); diff --git a/src/udp_collector.cpp b/src/udp_collector.cpp index 166c580..a7faf67 100644 --- a/src/udp_collector.cpp +++ b/src/udp_collector.cpp @@ -491,17 +491,13 @@ epicsThreadOnceId collector_once = EPICS_THREAD_ONCE_INIT; void collector_init(void *unused) { (void)unused; - try { - udp_gbl = new udp_gbl_t; - }catch(std::exception& e){ - log_exc_printf(logsetup, "Unable to alloc udp_gbl: %s\n", e.what()); - } + udp_gbl = new udp_gbl_t; } } // namespace UDPManager UDPManager::instance() { - epicsThreadOnce(&collector_once, &collector_init, nullptr); + threadOnce(&collector_once, &collector_init, nullptr); assert(udp_gbl); Guard G(udp_gbl->lock); diff --git a/src/util.cpp b/src/util.cpp index cd10964..18ad8a3 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -439,6 +439,31 @@ std::ostream& operator<<(std::ostream& strm, const SockAddr& addr) namespace pvxs {namespace impl { +struct onceArgs { + EPICSTHREADFUNC fn; + void *arg; + std::exception_ptr err; +}; + +static +void onceWrapper(void *raw) +{ + auto args = static_cast(raw); + try { + args->fn(args->arg); + }catch(...){ + args->err = std::current_exception(); + } +} + +void threadOnce(epicsThreadOnceId *id, EPICSTHREADFUNC fn, void *arg) +{ + onceArgs args{fn, arg}; + epicsThreadOnce(id, &onceWrapper, &args); + if(args.err) + std::rethrow_exception(args.err); +} + template<> double parseTo(const std::string& s) { size_t idx=0, L=s.size(); diff --git a/src/utilpvt.h b/src/utilpvt.h index 254f0c8..31d5742 100644 --- a/src/utilpvt.h +++ b/src/utilpvt.h @@ -41,6 +41,8 @@ # endif #endif +#include + namespace pvxs {namespace impl { //! in-line string builder (eg. for exception messages) @@ -53,6 +55,9 @@ struct SB { SB& operator<<(const T& i) { strm< struct Range {