diff --git a/rclpy/src/rclpy/context.cpp b/rclpy/src/rclpy/context.cpp index 6d7219a79..079ab02cb 100644 --- a/rclpy/src/rclpy/context.cpp +++ b/rclpy/src/rclpy/context.cpp @@ -150,17 +150,18 @@ Context::ok() void Context::shutdown() { - { - std::lock_guard guard{g_contexts_mutex}; - auto iter = std::find(g_contexts.begin(), g_contexts.end(), rcl_context_.get()); - if (iter != g_contexts.end()) { - g_contexts.erase(iter); - } + std::lock_guard guard{g_contexts_mutex}; + if (already_shutdown_) { + throw CONTEXT_ALREADY_SHUTDOWN("Context already shutdown."); } - - rcl_ret_t ret = rcl_shutdown(rcl_context_.get()); - if (RCL_RET_OK != ret) { - throw RCLError("failed to shutdown"); + auto iter = std::find(g_contexts.begin(), g_contexts.end(), rcl_context_.get()); + if (iter != g_contexts.end()) { + g_contexts.erase(iter); + rcl_ret_t ret = rcl_shutdown(rcl_context_.get()); + if (RCL_RET_OK != ret) { + throw RCLError("failed to shutdown"); + } + already_shutdown_ = true; } } diff --git a/rclpy/src/rclpy/context.hpp b/rclpy/src/rclpy/context.hpp index cdeb14122..30259e3e4 100644 --- a/rclpy/src/rclpy/context.hpp +++ b/rclpy/src/rclpy/context.hpp @@ -101,6 +101,7 @@ class Context : public Destroyable, public std::enable_shared_from_this private: std::shared_ptr rcl_context_; + bool already_shutdown_{false}; }; /// Define a pybind11 wrapper for an rclpy::Context diff --git a/rclpy/src/rclpy/exceptions.hpp b/rclpy/src/rclpy/exceptions.hpp index 521146fd0..9146b794d 100644 --- a/rclpy/src/rclpy/exceptions.hpp +++ b/rclpy/src/rclpy/exceptions.hpp @@ -80,6 +80,11 @@ class InvalidHandle : public std::runtime_error using std::runtime_error::runtime_error; }; +class CONTEXT_ALREADY_SHUTDOWN : public std::runtime_error +{ + using std::runtime_error::runtime_error; +}; + } // namespace rclpy #endif // RCLPY__EXCEPTIONS_HPP_