@@ -128,27 +128,54 @@ void OBCameraNode::clean() noexcept {
128128 std::lock_guard<decltype (device_lock_)> lock (device_lock_);
129129 RCLCPP_WARN_STREAM (logger_, " Do destroy ~OBCameraNode" );
130130 is_running_.store (false );
131+
132+ // Stop diagnostic timer and updater first to prevent access to disconnected device
133+ try {
134+ if (diagnostic_timer_) {
135+ diagnostic_timer_->cancel ();
136+ diagnostic_timer_.reset ();
137+ }
138+ if (diagnostic_updater_) {
139+ diagnostic_updater_.reset ();
140+ }
141+ } catch (...) {
142+ // Ignore exceptions during diagnostic cleanup
143+ }
144+
131145 RCLCPP_WARN_STREAM (logger_, " Stop tf thread" );
132- if (tf_thread_ && tf_thread_->joinable ()) {
133- tf_thread_->join ();
146+ try {
147+ if (tf_thread_ && tf_thread_->joinable ()) {
148+ tf_cv_.notify_all (); // Wake up tf thread if it's waiting
149+ tf_thread_->join ();
150+ }
151+ } catch (...) {
152+ RCLCPP_WARN_STREAM (logger_, " Exception while stopping tf thread" );
134153 }
154+
135155 RCLCPP_WARN_STREAM (logger_, " Stop color frame thread" );
136- if (colorFrameThread_ && colorFrameThread_->joinable ()) {
137- color_frame_queue_cv_.notify_all ();
138- colorFrameThread_->join ();
156+ try {
157+ if (colorFrameThread_ && colorFrameThread_->joinable ()) {
158+ color_frame_queue_cv_.notify_all ();
159+ colorFrameThread_->join ();
160+ }
161+ } catch (...) {
162+ RCLCPP_WARN_STREAM (logger_, " Exception while stopping color frame thread" );
139163 }
140164
141165 RCLCPP_WARN_STREAM (logger_, " stop streams" );
142- stopStreams ();
143- stopIMU ();
144- delete[] rgb_buffer_;
145- rgb_buffer_ = nullptr ;
146-
147- delete[] depth_xy_table_data_;
148- depth_xy_table_data_ = nullptr ;
166+ try {
167+ stopStreams ();
168+ stopIMU ();
169+ } catch (...) {
170+ RCLCPP_WARN_STREAM (logger_, " Exception while stopping streams" );
171+ }
149172
150- delete[] depth_point_cloud_buffer_;
151- depth_point_cloud_buffer_ = nullptr ;
173+ try {
174+ delete[] rgb_buffer_;
175+ rgb_buffer_ = nullptr ;
176+ } catch (...) {
177+ RCLCPP_WARN_STREAM (logger_, " Exception while cleaning up buffers" );
178+ }
152179
153180 RCLCPP_WARN_STREAM (logger_, " Destroy ~OBCameraNode DONE" );
154181}
@@ -1410,22 +1437,53 @@ void OBCameraNode::startIMU() {
14101437}
14111438
14121439void OBCameraNode::stopStreams () {
1440+ std::lock_guard<decltype (device_lock_)> lock (device_lock_);
1441+
14131442 if (!pipeline_started_ || !pipeline_) {
14141443 RCLCPP_INFO_STREAM (logger_, " pipeline not started or not exist, skip stop pipeline" );
14151444 return ;
14161445 }
1446+
1447+ // Stop diagnostic timer first to prevent crashes during shutdown
1448+ try {
1449+ if (diagnostic_timer_) {
1450+ diagnostic_timer_->cancel ();
1451+ diagnostic_timer_.reset ();
1452+ }
1453+ if (diagnostic_updater_) {
1454+ diagnostic_updater_.reset ();
1455+ }
1456+ } catch (...) {
1457+ // Ignore exceptions during diagnostic cleanup
1458+ }
1459+
1460+ // Mark pipeline as stopping to prevent new operations
1461+ pipeline_started_.store (false );
1462+
14171463 try {
1418- pipeline_->stop ();
1419- // disable interleave frame
1420- if ((interleave_ae_mode_ == " hdr" ) || (interleave_ae_mode_ == " laser" )) {
1421- RCLCPP_INFO_STREAM (logger_, " current interleave_ae_mode_: " << interleave_ae_mode_);
1422- if (device_->isPropertySupported (OB_PROP_FRAME_INTERLEAVE_ENABLE_BOOL, OB_PERMISSION_WRITE)) {
1423- interleave_frame_enable_ = false ;
1424- RCLCPP_INFO_STREAM (logger_, " Enable enable_interleave_depth_frame to "
1425- << (interleave_frame_enable_ ? " true" : " false" ));
1426- TRY_TO_SET_PROPERTY (setBoolProperty, OB_PROP_FRAME_INTERLEAVE_ENABLE_BOOL,
1427- interleave_frame_enable_);
1464+ // Check if device is still valid before stopping pipeline
1465+ if (device_ && pipeline_) {
1466+ pipeline_->stop ();
1467+
1468+ // disable interleave frame only if device is still connected
1469+ if ((interleave_ae_mode_ == " hdr" ) || (interleave_ae_mode_ == " laser" )) {
1470+ try {
1471+ RCLCPP_INFO_STREAM (logger_, " current interleave_ae_mode_: " << interleave_ae_mode_);
1472+ if (device_->isPropertySupported (OB_PROP_FRAME_INTERLEAVE_ENABLE_BOOL, OB_PERMISSION_WRITE)) {
1473+ interleave_frame_enable_ = false ;
1474+ RCLCPP_INFO_STREAM (logger_, " Enable enable_interleave_depth_frame to "
1475+ << (interleave_frame_enable_ ? " true" : " false" ));
1476+ TRY_TO_SET_PROPERTY (setBoolProperty, OB_PROP_FRAME_INTERLEAVE_ENABLE_BOOL,
1477+ interleave_frame_enable_);
1478+ }
1479+ } catch (const ob::Error &e) {
1480+ RCLCPP_WARN_STREAM (logger_, " Failed to disable interleave frame during shutdown: " << e.getMessage ());
1481+ } catch (...) {
1482+ RCLCPP_WARN_STREAM (logger_, " Failed to disable interleave frame during shutdown" );
1483+ }
14281484 }
1485+ } else {
1486+ RCLCPP_WARN_STREAM (logger_, " Device or pipeline not available during stop - likely disconnected" );
14291487 }
14301488 } catch (const ob::Error &e) {
14311489 RCLCPP_ERROR_STREAM (logger_, " Failed to stop pipeline: " << e.getMessage ());
@@ -1435,6 +1493,8 @@ void OBCameraNode::stopStreams() {
14351493}
14361494
14371495void OBCameraNode::stopIMU () {
1496+ std::lock_guard<decltype (device_lock_)> lock (device_lock_);
1497+
14381498 if (enable_sync_output_accel_gyro_) {
14391499 if (!imu_sync_output_start_ || !imuPipeline_) {
14401500 RCLCPP_INFO_STREAM (logger_, " imu pipeline not started or not exist, skip stop imu pipeline" );
@@ -1880,6 +1940,14 @@ void OBCameraNode::setupTopics() {
18801940
18811941void OBCameraNode::onTemperatureUpdate (diagnostic_updater::DiagnosticStatusWrapper &status) {
18821942 try {
1943+
1944+ // check to ensure we're not shutting down
1945+ std::lock_guard<decltype (device_lock_)> lock (device_lock_);
1946+ if (!device_ || !is_running_.load ()) {
1947+ status.summary (diagnostic_msgs::msg::DiagnosticStatus::STALE, " Device disconnected" );
1948+ return ;
1949+ }
1950+
18831951 OBDeviceTemperature temperature;
18841952 uint32_t data_size = sizeof (OBDeviceTemperature);
18851953 device_->getStructuredData (OB_STRUCT_DEVICE_TEMPERATURE,
@@ -1897,17 +1965,38 @@ void OBCameraNode::onTemperatureUpdate(diagnostic_updater::DiagnosticStatusWrapp
18971965 status.add (" Chip Bottom Temperature" , temperature.chipBottomTemp );
18981966 status.summary (diagnostic_msgs::msg::DiagnosticStatus::OK, " Temperature is normal" );
18991967 } catch (const ob::Error &e) {
1900- if (is_running_.load ()) {
1901- diagnostic_timer_->cancel ();
1902- diagnostic_timer_.reset ();
1968+ try {
1969+ if (is_running_.load () && diagnostic_timer_) {
1970+ diagnostic_timer_->cancel ();
1971+ diagnostic_timer_.reset ();
1972+ }
1973+ } catch (...) {
1974+ // Ignore exceptions during cleanup
19031975 }
19041976 RCLCPP_ERROR_STREAM (logger_, " Failed to TemperatureUpdate: " << e.getMessage ());
19051977 status.summary (diagnostic_msgs::msg::DiagnosticStatus::ERROR, e.getMessage ());
19061978 } catch (const std::exception &e) {
1979+ try {
1980+ if (is_running_.load () && diagnostic_timer_) {
1981+ diagnostic_timer_->cancel ();
1982+ diagnostic_timer_.reset ();
1983+ }
1984+ } catch (...) {
1985+ // Ignore exceptions during cleanup
1986+ }
19071987 RCLCPP_ERROR_STREAM (logger_, " Failed to TemperatureUpdate: " << e.what ());
19081988 status.summary (diagnostic_msgs::msg::DiagnosticStatus::ERROR, e.what ());
19091989 } catch (...) {
1990+ try {
1991+ if (is_running_.load () && diagnostic_timer_) {
1992+ diagnostic_timer_->cancel ();
1993+ diagnostic_timer_.reset ();
1994+ }
1995+ } catch (...) {
1996+ // Ignore exceptions during cleanup
1997+ }
19101998 RCLCPP_ERROR (logger_, " Failed to TemperatureUpdate" );
1999+ status.summary (diagnostic_msgs::msg::DiagnosticStatus::ERROR, " Unknown error" );
19112000 }
19122001}
19132002
0 commit comments