Skip to content

Commit 024d36a

Browse files
vividfpre-commit-ci[bot]SakodaShintaro
committed
fix(autoware_pointcloud_preprocessor): fix potential double unlock in concatenate node (autowarefoundation#10082)
* feat: reuse collectors Signed-off-by: vividf <yihsiang.fang@tier4.jp> * fix: potential double unlock Signed-off-by: vividf <yihsiang.fang@tier4.jp> * style(pre-commit): autofix * chore: remove mutex Signed-off-by: vividf <yihsiang.fang@tier4.jp> * chore: reset the processing cloud only if needed Signed-off-by: vividf <yihsiang.fang@tier4.jp> * chore: fix grammar Signed-off-by: vividf <yihsiang.fang@tier4.jp> --------- Signed-off-by: vividf <yihsiang.fang@tier4.jp> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: SakodaShintaro <shintaro.sakoda@tier4.jp>
1 parent 64eaa47 commit 024d36a

File tree

6 files changed

+61
-79
lines changed

6 files changed

+61
-79
lines changed

sensing/autoware_pointcloud_preprocessor/include/autoware/pointcloud_preprocessor/concatenate_data/cloud_collector.hpp

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2024 TIER IV, Inc.
1+
// Copyright 2025 TIER IV, Inc.
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -59,7 +59,7 @@ class CloudCollector
5959
std::shared_ptr<CombineCloudHandler> & combine_cloud_handler, int num_of_clouds,
6060
double timeout_sec, bool debug_mode);
6161
bool topic_exists(const std::string & topic_name);
62-
bool process_pointcloud(
62+
void process_pointcloud(
6363
const std::string & topic_name, sensor_msgs::msg::PointCloud2::SharedPtr cloud);
6464
void concatenate_callback();
6565

@@ -69,7 +69,7 @@ class CloudCollector
6969
std::unordered_map<std::string, sensor_msgs::msg::PointCloud2::SharedPtr>
7070
get_topic_to_cloud_map();
7171

72-
[[nodiscard]] CollectorStatus get_status();
72+
[[nodiscard]] CollectorStatus get_status() const;
7373

7474
void set_info(std::shared_ptr<CollectorInfoBase> collector_info);
7575
[[nodiscard]] std::shared_ptr<CollectorInfoBase> get_info() const;
@@ -84,7 +84,6 @@ class CloudCollector
8484
uint64_t num_of_clouds_;
8585
double timeout_sec_;
8686
bool debug_mode_;
87-
std::mutex concatenate_mutex_;
8887
std::shared_ptr<CollectorInfoBase> collector_info_;
8988
CollectorStatus status_;
9089
};

sensing/autoware_pointcloud_preprocessor/include/autoware/pointcloud_preprocessor/concatenate_data/collector_matching_strategy.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2024 TIER IV, Inc.
1+
// Copyright 2025 TIER IV, Inc.
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.

sensing/autoware_pointcloud_preprocessor/include/autoware/pointcloud_preprocessor/concatenate_data/combine_cloud_handler.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2024 TIER IV, Inc.
1+
// Copyright 2025 TIER IV, Inc.
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.

sensing/autoware_pointcloud_preprocessor/include/autoware/pointcloud_preprocessor/concatenate_data/concatenate_and_time_sync_node.hpp

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2023 TIER IV, Inc.
1+
// Copyright 2025 TIER IV, Inc.
22
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -16,7 +16,6 @@
1616

1717
#include <list>
1818
#include <memory>
19-
#include <mutex>
2019
#include <string>
2120
#include <unordered_map>
2221
#include <vector>
@@ -91,7 +90,6 @@ class PointCloudConcatenateDataSynchronizerComponent : public rclcpp::Node
9190
std::shared_ptr<CombineCloudHandler> combine_cloud_handler_;
9291
std::list<std::shared_ptr<CloudCollector>> cloud_collectors_;
9392
std::unique_ptr<CollectorMatchingStrategy> collector_matching_strategy_;
94-
std::mutex cloud_collectors_mutex_;
9593
bool init_collector_list_ = false;
9694
static constexpr const int num_of_collectors = 3;
9795

@@ -122,6 +120,7 @@ class PointCloudConcatenateDataSynchronizerComponent : public rclcpp::Node
122120
std::string replace_sync_topic_name_postfix(
123121
const std::string & original_topic_name, const std::string & postfix);
124122
void initialize_collector_list();
123+
std::list<std::shared_ptr<CloudCollector>>::iterator find_and_reset_oldest_collector();
125124
};
126125

127126
} // namespace autoware::pointcloud_preprocessor

sensing/autoware_pointcloud_preprocessor/src/concatenate_data/cloud_collector.cpp

+2-13
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ CloudCollector::CloudCollector(
4444

4545
timer_ =
4646
rclcpp::create_timer(ros2_parent_node_, ros2_parent_node_->get_clock(), period_ns, [this]() {
47-
std::lock_guard<std::mutex> concatenate_lock(concatenate_mutex_);
4847
if (status_ == CollectorStatus::Finished) return;
4948
concatenate_callback();
5049
});
@@ -67,14 +66,9 @@ bool CloudCollector::topic_exists(const std::string & topic_name)
6766
return topic_to_cloud_map_.find(topic_name) != topic_to_cloud_map_.end();
6867
}
6968

70-
bool CloudCollector::process_pointcloud(
69+
void CloudCollector::process_pointcloud(
7170
const std::string & topic_name, sensor_msgs::msg::PointCloud2::SharedPtr cloud)
7271
{
73-
std::lock_guard<std::mutex> concatenate_lock(concatenate_mutex_);
74-
if (status_ == CollectorStatus::Finished) {
75-
return false;
76-
}
77-
7872
if (status_ == CollectorStatus::Idle) {
7973
// Add first pointcloud to the collector, restart the timer
8074
status_ = CollectorStatus::Processing;
@@ -95,13 +89,10 @@ bool CloudCollector::process_pointcloud(
9589
if (topic_to_cloud_map_.size() == num_of_clouds_) {
9690
concatenate_callback();
9791
}
98-
99-
return true;
10092
}
10193

102-
CollectorStatus CloudCollector::get_status()
94+
CollectorStatus CloudCollector::get_status() const
10395
{
104-
std::lock_guard<std::mutex> concatenate_lock(concatenate_mutex_);
10596
return status_;
10697
}
10798

@@ -168,8 +159,6 @@ void CloudCollector::show_debug_message()
168159

169160
void CloudCollector::reset()
170161
{
171-
std::lock_guard<std::mutex> lock(concatenate_mutex_);
172-
173162
status_ = CollectorStatus::Idle; // Reset status to Idle
174163
topic_to_cloud_map_.clear();
175164
collector_info_ = nullptr;

sensing/autoware_pointcloud_preprocessor/src/concatenate_data/concatenate_and_time_sync_node.cpp

+52-57
Original file line numberDiff line numberDiff line change
@@ -227,10 +227,9 @@ void PointCloudConcatenateDataSynchronizerComponent::cloud_callback(
227227
this->get_logger(), *this->get_clock(), 1000, "Empty sensor points!");
228228
}
229229

230-
// protect cloud collectors list
231-
std::unique_lock<std::mutex> cloud_collectors_lock(cloud_collectors_mutex_);
230+
std::shared_ptr<CloudCollector> selected_collector = nullptr;
232231

233-
// For each callback, check whether there is a exist collector that matches this cloud
232+
// For each callback, check whether there is an existing collector that matches this cloud
234233
std::optional<std::shared_ptr<CloudCollector>> cloud_collector = std::nullopt;
235234
MatchingParams matching_params;
236235
matching_params.topic_name = topic_name;
@@ -242,36 +241,36 @@ void PointCloudConcatenateDataSynchronizerComponent::cloud_callback(
242241
collector_matching_strategy_->match_cloud_to_collector(cloud_collectors_, matching_params);
243242
}
244243

245-
bool process_success = false;
246-
if (cloud_collector.has_value()) {
247-
auto collector = cloud_collector.value();
248-
if (collector) {
249-
cloud_collectors_lock.unlock();
250-
process_success = collector->process_pointcloud(topic_name, input_ptr);
251-
}
244+
if (cloud_collector.has_value() && cloud_collector.value()) {
245+
selected_collector = cloud_collector.value();
252246
}
253247

254248
// Didn't find matched collector
255-
if (!process_success) {
256-
// Reuse the collector if the status is IDLE
257-
std::shared_ptr<CloudCollector> selected_collector = nullptr;
258-
249+
if (!selected_collector || selected_collector->get_status() == CollectorStatus::Finished) {
250+
// Reuse a collector if one is in the IDLE state
259251
auto it = std::find_if(
260252
cloud_collectors_.begin(), cloud_collectors_.end(),
261253
[](const auto & collector) { return collector->get_status() == CollectorStatus::Idle; });
262254

263255
if (it != cloud_collectors_.end()) {
264256
selected_collector = *it;
257+
} else {
258+
auto oldest_it = find_and_reset_oldest_collector();
259+
if (oldest_it != cloud_collectors_.end()) {
260+
selected_collector = *oldest_it;
261+
} else {
262+
// Handle case where no suitable collector is found
263+
RCLCPP_ERROR(get_logger(), "No available CloudCollector in IDLE state.");
264+
return;
265+
}
265266
}
266-
cloud_collectors_lock.unlock();
267+
267268
if (selected_collector) {
268269
collector_matching_strategy_->set_collector_info(selected_collector, matching_params);
269-
(void)selected_collector->process_pointcloud(topic_name, input_ptr);
270-
} else {
271-
// Handle case where no suitable collector is found
272-
RCLCPP_WARN(get_logger(), "No available CloudCollector in IDLE state.");
273270
}
274271
}
272+
273+
selected_collector->process_pointcloud(topic_name, input_ptr);
275274
}
276275

277276
void PointCloudConcatenateDataSynchronizerComponent::twist_callback(
@@ -371,55 +370,51 @@ void PointCloudConcatenateDataSynchronizerComponent::publish_clouds(
371370

372371
void PointCloudConcatenateDataSynchronizerComponent::manage_collector_list()
373372
{
374-
std::lock_guard<std::mutex> cloud_collectors_lock(cloud_collectors_mutex_);
375-
376-
int num_processing_collectors = 0;
377-
378373
for (auto & collector : cloud_collectors_) {
379374
if (collector->get_status() == CollectorStatus::Finished) {
380375
collector->reset();
381376
}
382-
383-
if (collector->get_status() == CollectorStatus::Processing) {
384-
num_processing_collectors++;
385-
}
386377
}
378+
}
387379

388-
if (num_processing_collectors == num_of_collectors) {
389-
auto min_it = cloud_collectors_.end();
390-
constexpr double k_max_timestamp = std::numeric_limits<double>::max();
391-
double min_timestamp = k_max_timestamp;
392-
393-
for (auto it = cloud_collectors_.begin(); it != cloud_collectors_.end(); ++it) {
394-
if ((*it)->get_status() == CollectorStatus::Processing) {
395-
auto info = (*it)->get_info();
396-
double timestamp = k_max_timestamp;
397-
398-
if (auto naive_info = std::dynamic_pointer_cast<NaiveCollectorInfo>(info)) {
399-
timestamp = naive_info->timestamp;
400-
} else if (auto advanced_info = std::dynamic_pointer_cast<AdvancedCollectorInfo>(info)) {
401-
timestamp = advanced_info->timestamp;
402-
} else {
403-
continue;
404-
}
380+
std::list<std::shared_ptr<CloudCollector>>::iterator
381+
PointCloudConcatenateDataSynchronizerComponent::find_and_reset_oldest_collector()
382+
{
383+
auto min_it = cloud_collectors_.end();
384+
constexpr double k_max_timestamp = std::numeric_limits<double>::max();
385+
double min_timestamp = k_max_timestamp;
386+
387+
for (auto it = cloud_collectors_.begin(); it != cloud_collectors_.end(); ++it) {
388+
if ((*it)->get_status() == CollectorStatus::Processing) {
389+
auto info = (*it)->get_info();
390+
double timestamp = k_max_timestamp;
391+
392+
if (auto naive_info = std::dynamic_pointer_cast<NaiveCollectorInfo>(info)) {
393+
timestamp = naive_info->timestamp;
394+
} else if (auto advanced_info = std::dynamic_pointer_cast<AdvancedCollectorInfo>(info)) {
395+
timestamp = advanced_info->timestamp;
396+
} else {
397+
continue;
398+
}
405399

406-
if (timestamp < min_timestamp) {
407-
min_timestamp = timestamp;
408-
min_it = it;
409-
}
400+
if (timestamp < min_timestamp) {
401+
min_timestamp = timestamp;
402+
min_it = it;
410403
}
411404
}
405+
}
412406

413-
// Reset the collector with the oldest timestamp if found
414-
if (min_it != cloud_collectors_.end()) {
415-
RCLCPP_WARN_STREAM_THROTTLE(
416-
this->get_logger(), *this->get_clock(), 1000,
417-
"Reset the oldest collector because the number of processing collectors ("
418-
<< num_processing_collectors << ") is equal to the limit of (" << num_of_collectors
419-
<< ").");
420-
(*min_it)->reset();
421-
}
407+
// Reset the processing collector with the oldest timestamp if found
408+
if (min_it != cloud_collectors_.end()) {
409+
RCLCPP_WARN_STREAM_THROTTLE(
410+
this->get_logger(), *this->get_clock(), 1000,
411+
"Reset the oldest collector because the number of processing collectors is equal to the "
412+
"limit of ("
413+
<< num_of_collectors << ").");
414+
(*min_it)->reset();
422415
}
416+
417+
return min_it;
423418
}
424419

425420
std::string PointCloudConcatenateDataSynchronizerComponent::format_timestamp(double timestamp)

0 commit comments

Comments
 (0)