Ensure logging is initialized just once (#998)
Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
This commit is contained in:
parent
e64022f753
commit
80e8dcad02
4 changed files with 88 additions and 1 deletions
|
@ -338,6 +338,9 @@ private:
|
||||||
rclcpp::InitOptions init_options_;
|
rclcpp::InitOptions init_options_;
|
||||||
std::string shutdown_reason_;
|
std::string shutdown_reason_;
|
||||||
|
|
||||||
|
// Keep shared ownership of global logging configure mutex.
|
||||||
|
std::shared_ptr<std::mutex> logging_configure_mutex_;
|
||||||
|
|
||||||
std::unordered_map<std::type_index, std::shared_ptr<void>> sub_contexts_;
|
std::unordered_map<std::type_index, std::shared_ptr<void>> sub_contexts_;
|
||||||
// This mutex is recursive so that the constructor of a sub context may
|
// This mutex is recursive so that the constructor of a sub context may
|
||||||
// attempt to acquire another sub context.
|
// attempt to acquire another sub context.
|
||||||
|
|
|
@ -42,6 +42,16 @@ public:
|
||||||
RCLCPP_PUBLIC
|
RCLCPP_PUBLIC
|
||||||
InitOptions(const InitOptions & other);
|
InitOptions(const InitOptions & other);
|
||||||
|
|
||||||
|
/// Return `true` if logging should be initialized when `rclcpp::Context::init` is called.
|
||||||
|
RCLCPP_PUBLIC
|
||||||
|
bool
|
||||||
|
auto_initialize_logging() const;
|
||||||
|
|
||||||
|
/// Set flag indicating if logging should be initialized or not.
|
||||||
|
RCLCPP_PUBLIC
|
||||||
|
InitOptions &
|
||||||
|
auto_initialize_logging(bool initialize_logging);
|
||||||
|
|
||||||
/// Assignment operator.
|
/// Assignment operator.
|
||||||
RCLCPP_PUBLIC
|
RCLCPP_PUBLIC
|
||||||
InitOptions &
|
InitOptions &
|
||||||
|
@ -62,6 +72,7 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<rcl_init_options_t> init_options_;
|
std::unique_ptr<rcl_init_options_t> init_options_;
|
||||||
|
bool initialize_logging_{true};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace rclcpp
|
} // namespace rclcpp
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "rcl/init.h"
|
#include "rcl/init.h"
|
||||||
|
#include "rcl/logging.h"
|
||||||
#include "rclcpp/detail/utilities.hpp"
|
#include "rclcpp/detail/utilities.hpp"
|
||||||
#include "rclcpp/exceptions.hpp"
|
#include "rclcpp/exceptions.hpp"
|
||||||
#include "rclcpp/logging.hpp"
|
#include "rclcpp/logging.hpp"
|
||||||
|
@ -34,8 +35,27 @@ static std::vector<std::weak_ptr<rclcpp::Context>> g_contexts;
|
||||||
|
|
||||||
using rclcpp::Context;
|
using rclcpp::Context;
|
||||||
|
|
||||||
|
static
|
||||||
|
std::shared_ptr<std::mutex>
|
||||||
|
get_global_logging_configure_mutex()
|
||||||
|
{
|
||||||
|
static auto mutex = std::make_shared<std::mutex>();
|
||||||
|
return mutex;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
size_t &
|
||||||
|
get_logging_reference_count()
|
||||||
|
{
|
||||||
|
static size_t ref_count = 0;
|
||||||
|
return ref_count;
|
||||||
|
}
|
||||||
|
|
||||||
Context::Context()
|
Context::Context()
|
||||||
: rcl_context_(nullptr), shutdown_reason_("") {}
|
: rcl_context_(nullptr),
|
||||||
|
shutdown_reason_(""),
|
||||||
|
logging_configure_mutex_(nullptr)
|
||||||
|
{}
|
||||||
|
|
||||||
Context::~Context()
|
Context::~Context()
|
||||||
{
|
{
|
||||||
|
@ -94,6 +114,30 @@ Context::init(
|
||||||
rcl_context_.reset();
|
rcl_context_.reset();
|
||||||
rclcpp::exceptions::throw_from_rcl_error(ret, "failed to initialize rcl");
|
rclcpp::exceptions::throw_from_rcl_error(ret, "failed to initialize rcl");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (init_options.auto_initialize_logging()) {
|
||||||
|
logging_configure_mutex_ = get_global_logging_configure_mutex();
|
||||||
|
if (!logging_configure_mutex_) {
|
||||||
|
throw std::runtime_error("global logging configure mutex is 'nullptr'");
|
||||||
|
}
|
||||||
|
std::lock_guard<std::mutex> guard(*logging_configure_mutex_);
|
||||||
|
size_t & count = get_logging_reference_count();
|
||||||
|
if (0u == count) {
|
||||||
|
ret = rcl_logging_configure(
|
||||||
|
&rcl_context_->global_arguments,
|
||||||
|
rcl_init_options_get_allocator(init_options_.get_rcl_init_options()));
|
||||||
|
if (RCL_RET_OK != ret) {
|
||||||
|
rcl_context_.reset();
|
||||||
|
rclcpp::exceptions::throw_from_rcl_error(ret, "failed to configure logging");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
RCLCPP_WARN(
|
||||||
|
rclcpp::get_logger("rclcpp"),
|
||||||
|
"logging was initialized more than once");
|
||||||
|
}
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
std::vector<std::string> unparsed_ros_arguments = detail::get_unparsed_ros_arguments(
|
std::vector<std::string> unparsed_ros_arguments = detail::get_unparsed_ros_arguments(
|
||||||
argc, argv, &(rcl_context_->global_arguments), rcl_get_default_allocator());
|
argc, argv, &(rcl_context_->global_arguments), rcl_get_default_allocator());
|
||||||
|
@ -183,6 +227,22 @@ Context::shutdown(const std::string & reason)
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// shutdown logger
|
||||||
|
if (logging_configure_mutex_) {
|
||||||
|
// logging was initialized by this context
|
||||||
|
std::lock_guard<std::mutex> guard(*logging_configure_mutex_);
|
||||||
|
size_t & count = get_logging_reference_count();
|
||||||
|
if (0u == --count) {
|
||||||
|
rcl_ret_t rcl_ret = rcl_logging_fini();
|
||||||
|
if (RCL_RET_OK != rcl_ret) {
|
||||||
|
RCUTILS_SAFE_FWRITE_TO_STDERR(
|
||||||
|
RCUTILS_STRINGIFY(__file__) ":"
|
||||||
|
RCUTILS_STRINGIFY(__LINE__)
|
||||||
|
" failed to fini logging");
|
||||||
|
rcl_reset_error();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,19 @@ InitOptions::InitOptions(const InitOptions & other)
|
||||||
shutdown_on_sigint = other.shutdown_on_sigint;
|
shutdown_on_sigint = other.shutdown_on_sigint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
InitOptions::auto_initialize_logging() const
|
||||||
|
{
|
||||||
|
return initialize_logging_;
|
||||||
|
}
|
||||||
|
|
||||||
|
InitOptions &
|
||||||
|
InitOptions::auto_initialize_logging(bool initialize_logging)
|
||||||
|
{
|
||||||
|
initialize_logging_ = initialize_logging;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
InitOptions &
|
InitOptions &
|
||||||
InitOptions::operator=(const InitOptions & other)
|
InitOptions::operator=(const InitOptions & other)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue