diff --git a/src/client.cpp b/src/client.cpp index 7089582..8ae162e 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -568,7 +568,7 @@ void Context::Pvt::onSearchS(evutil_socket_t fd, short evt, void *raw) for(unsigned i=0; i<4 && static_cast(raw)->onSearch(); i++) {} }catch(std::exception& e){ - log_crit_printf(io, "Unhandled error in search Rx callback: %s\n", e.what()); + log_exc_printf(io, "Unhandled error in search Rx callback: %s\n", e.what()); } } @@ -693,7 +693,7 @@ void Context::Pvt::tickSearchS(evutil_socket_t fd, short evt, void *raw) try { static_cast(raw)->tickSearch(); }catch(std::exception& e){ - log_crit_printf(io, "Unhandled error in search timer callback: %s\n", e.what()); + log_exc_printf(io, "Unhandled error in search timer callback: %s\n", e.what()); } } @@ -724,7 +724,7 @@ void Context::Pvt::tickBeaconCleanS(evutil_socket_t fd, short evt, void *raw) try { static_cast(raw)->tickBeaconClean(); }catch(std::exception& e){ - log_crit_printf(io, "Unhandled error in beacon cleaner timer callback: %s\n", e.what()); + log_exc_printf(io, "Unhandled error in beacon cleaner timer callback: %s\n", e.what()); } } diff --git a/src/clientconn.cpp b/src/clientconn.cpp index bac9ddd..4aadf0a 100644 --- a/src/clientconn.cpp +++ b/src/clientconn.cpp @@ -402,7 +402,7 @@ void Connection::tickEchoS(evutil_socket_t fd, short evt, void *raw) try { static_cast(raw)->tickEcho(); }catch(std::exception& e){ - log_crit_printf(io, "Unhandled error in echo timer callback: %s\n", e.what()); + log_exc_printf(io, "Unhandled error in echo timer callback: %s\n", e.what()); } } diff --git a/src/clientintrospect.cpp b/src/clientintrospect.cpp index 8927833..ceb8c8d 100644 --- a/src/clientintrospect.cpp +++ b/src/clientintrospect.cpp @@ -158,7 +158,7 @@ void Connection::handle_GET_FIELD() try { done(std::move(res)); }catch(std::exception& e){ - log_err_printf(setup, "Unhandled exception %s in Info result() callback: %s\n", typeid (e).name(), e.what()); + log_exc_printf(setup, "Unhandled exception %s in Info result() callback: %s\n", typeid (e).name(), e.what()); } } else { diff --git a/src/clientmon.cpp b/src/clientmon.cpp index 0c6b36a..83294ec 100644 --- a/src/clientmon.cpp +++ b/src/clientmon.cpp @@ -84,7 +84,7 @@ struct SubscriptionImpl : public OperationBase, public Subscription try { event(*this); }catch(std::exception& e){ - log_err_printf(io, "Unhandled user exception in Monitor %s %s : %s\n", + log_exc_printf(io, "Unhandled user exception in Monitor %s %s : %s\n", __func__, typeid (e).name(), e.what()); } } @@ -312,8 +312,8 @@ struct SubscriptionImpl : public OperationBase, public Subscription try { static_cast(raw)->tickAck(); }catch(std::exception& e) { - log_crit_printf(io, "Unhandled exception in %s %s : %s\n", - __func__, typeid (e).name(), e.what()); + log_exc_printf(io, "Unhandled exception in %s %s : %s\n", + __func__, typeid (e).name(), e.what()); } } }; diff --git a/src/conn.cpp b/src/conn.cpp index 0441e7c..4d350e3 100644 --- a/src/conn.cpp +++ b/src/conn.cpp @@ -219,7 +219,7 @@ void ConnBase::bevEventS(struct bufferevent *bev, short events, void *ptr) try { conn->bevEvent(events); }catch(std::exception& e){ - log_crit_printf(connsetup, "%s %s Unhandled error in bev event callback: %s\n", conn->peerLabel(), conn->peerName.c_str(), e.what()); + log_exc_printf(connsetup, "%s %s Unhandled error in bev event callback: %s\n", conn->peerLabel(), conn->peerName.c_str(), e.what()); conn->cleanup(); } } @@ -230,7 +230,7 @@ void ConnBase::bevReadS(struct bufferevent *bev, void *ptr) try { conn->bevRead(); }catch(std::exception& e){ - log_crit_printf(connsetup, "%s %s Unhandled error in bev read callback: %s\n", conn->peerLabel(), conn->peerName.c_str(), e.what()); + log_exc_printf(connsetup, "%s %s Unhandled error in bev read callback: %s\n", conn->peerLabel(), conn->peerName.c_str(), e.what()); conn->cleanup(); } } @@ -241,7 +241,7 @@ void ConnBase::bevWriteS(struct bufferevent *bev, void *ptr) try { conn->bevWrite(); }catch(std::exception& e){ - log_crit_printf(connsetup, "%s %s Unhandled error in bev write callback: %s\n", conn->peerLabel(), conn->peerName.c_str(), e.what()); + log_exc_printf(connsetup, "%s %s Unhandled error in bev write callback: %s\n", conn->peerLabel(), conn->peerName.c_str(), e.what()); conn->cleanup(); } } diff --git a/src/evhelper.cpp b/src/evhelper.cpp index e400d65..48f9518 100644 --- a/src/evhelper.cpp +++ b/src/evhelper.cpp @@ -133,7 +133,7 @@ struct evbase::Pvt : public epicsThreadRunable log_printf(logerr, lvl, "Exit loop worker: %d for %p\n", ret, base.get()); }catch(std::exception& e){ - log_crit_printf(logerr, "Unhandled exception in event_base run : %s\n", + log_exc_printf(logerr, "Unhandled exception in event_base run : %s\n", e.what()); start_sync.trigger(); } @@ -154,7 +154,7 @@ struct evbase::Pvt : public epicsThreadRunable Guard G(lock); *work.result = std::current_exception(); } else { - log_crit_printf(logerr, "Unhandled exception in event_base : %s : %s\n", + log_exc_printf(logerr, "Unhandled exception in event_base : %s : %s\n", typeid(e).name(), e.what()); } } @@ -169,7 +169,7 @@ struct evbase::Pvt : public epicsThreadRunable try { self->doWork(); }catch(std::exception& e){ - log_crit_printf(logerr, "Unhandled error in doWorkS callback: %s\n", e.what()); + log_exc_printf(logerr, "Unhandled error in doWorkS callback: %s\n", e.what()); } } diff --git a/src/log.cpp b/src/log.cpp index e0813e8..cf6df44 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -15,7 +15,9 @@ #include #include +#include #include +#include #include #include #include @@ -65,6 +67,13 @@ const char* log_prefix(const char* name, Level lvl) return prefix; } +void log_stacktrace() +{ + // stack traces can be long. flush to reduce truncation + errlogFlush(); + epicsStackTrace(); +} + } // namespace detail namespace { diff --git a/src/pvxs/log.h b/src/pvxs/log.h index e37553f..c048d6d 100644 --- a/src/pvxs/log.h +++ b/src/pvxs/log.h @@ -51,6 +51,9 @@ namespace detail { PVXS_API const char* log_prefix(const char* name, Level lvl); +PVXS_API +void log_stacktrace(); + } // namespace detail //! Define a new logger global. @@ -82,6 +85,13 @@ void xerrlogHexPrintf(const void *buf, size_t buflen); #define log_info_printf(LOGGER, ...) log_printf(LOGGER, ::pvxs::Level::Info, __VA_ARGS__) #define log_debug_printf(LOGGER, ...) log_printf(LOGGER, ::pvxs::Level::Debug, __VA_ARGS__) +#define log_exc_printf(LOGGER, FMT, ...) do{ \ + if((LOGGER).test(::pvxs::Level::Crit)) { \ + errlogPrintf("%s " FMT, ::pvxs::detail::log_prefix((LOGGER).name, ::pvxs::Level::Crit), __VA_ARGS__); \ + ::pvxs::detail::log_stacktrace(); \ + } \ +}while(0) + #define log_hex_printf(LOGGER, LVL, BUF, BUFLEN, FMT, ...) do{ if((LOGGER).test(LVL)) { \ xerrlogHexPrintf(BUF, BUFLEN); \ errlogPrintf("%s " FMT, ::pvxs::detail::log_prefix((LOGGER).name, LVL), __VA_ARGS__); } \ diff --git a/src/server.cpp b/src/server.cpp index b65c360..062d95e 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -441,7 +441,7 @@ void Server::Pvt::onSearch(const UDPManager::Search& msg) try { pair.second->onSearch(searchOp); }catch(std::exception& e){ - log_err_printf(serversetup, "Unhandled error in Source::onSearch for '%s' : %s\n", + log_exc_printf(serversetup, "Unhandled error in Source::onSearch for '%s' : %s\n", pair.first.second.c_str(), e.what()); } } @@ -554,7 +554,7 @@ void Server::Pvt::doBeaconsS(evutil_socket_t fd, short evt, void *raw) try { static_cast(raw)->doBeacons(evt); }catch(std::exception& e){ - log_crit_printf(serverio, "Unhandled error in beacon timer callback: %s\n", e.what()); + log_exc_printf(serverio, "Unhandled error in beacon timer callback: %s\n", e.what()); } } diff --git a/src/serverchan.cpp b/src/serverchan.cpp index 27a4a37..ab7f1ab 100644 --- a/src/serverchan.cpp +++ b/src/serverchan.cpp @@ -224,7 +224,7 @@ void ServerConn::handle_SEARCH() try { pair.second->onSearch(op); }catch(std::exception& e){ - log_err_printf(serversetup, "Unhandled error in Source::onSearch for '%s' : %s\n", + log_exc_printf(serversetup, "Unhandled error in Source::onSearch for '%s' : %s\n", pair.first.second.c_str(), e.what()); } } @@ -311,7 +311,7 @@ void ServerConn::handle_CREATE_CHANNEL() break; } }catch(std::exception& e){ - log_err_printf(connsetup, "Client %s Unhandled error in onCreate %s,%d %s : %s\n", peerName.c_str(), + log_exc_printf(connsetup, "Client %s Unhandled error in onCreate %s,%d %s : %s\n", peerName.c_str(), pair.first.second.c_str(), pair.first.first, typeid(&e).name(), e.what()); } diff --git a/src/serverconn.cpp b/src/serverconn.cpp index 0417563..5da38fe 100644 --- a/src/serverconn.cpp +++ b/src/serverconn.cpp @@ -388,7 +388,7 @@ void ServIface::onConnS(struct evconnlistener *listener, evutil_socket_t sock, s auto conn(std::make_shared(self, sock, peer, socklen)); self->server->connections[conn.get()] = std::move(conn); }catch(std::exception& e){ - log_crit_printf(connsetup, "Interface %s Unhandled error in accept callback: %s\n", self->name.c_str(), e.what()); + log_exc_printf(connsetup, "Interface %s Unhandled error in accept callback: %s\n", self->name.c_str(), e.what()); evutil_closesocket(sock); } }