Skip to content

Commit c123aae

Browse files
committed
TPC Cluster decoding: Fix use-after-free race condition bug in multi-threaded track-model decoding
1 parent 90c3064 commit c123aae

File tree

2 files changed

+5
-5
lines changed

2 files changed

+5
-5
lines changed

GPU/GPUTracking/DataCompression/TPCClusterDecompressor.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,6 @@ class TPCClusterDecompressor
4040
static void decompressTrack(const o2::tpc::CompressedClusters* clustersCompressed, const GPUParam& param, const unsigned int maxTime, const unsigned int i, unsigned int& offset, Args&... args);
4141
template <typename... Args>
4242
static void decompressHits(const o2::tpc::CompressedClusters* clustersCompressed, const unsigned int start, const unsigned int end, Args&... args);
43-
44-
protected:
4543
};
4644
} // namespace GPUCA_NAMESPACE::gpu
4745

GPU/GPUTracking/DataCompression/TPCClusterDecompressor.inc

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,17 @@ static inline const auto& decompressTrackStore(const o2::tpc::CompressedClusters
3737
return clusterVector.back();
3838
}
3939

40-
static inline const auto& decompressTrackStore(const o2::tpc::CompressedClusters* clustersCompressed, const unsigned int offset, unsigned int slice, unsigned int row, unsigned int pad, unsigned int time, std::vector<ClusterNative> (&clusters)[GPUCA_NSLICES][GPUCA_ROW_COUNT], std::atomic_flag (&locks)[GPUCA_NSLICES][GPUCA_ROW_COUNT])
40+
static inline const auto decompressTrackStore(const o2::tpc::CompressedClusters* clustersCompressed, const unsigned int offset, unsigned int slice, unsigned int row, unsigned int pad, unsigned int time, std::vector<ClusterNative> (&clusters)[GPUCA_NSLICES][GPUCA_ROW_COUNT], std::atomic_flag (&locks)[GPUCA_NSLICES][GPUCA_ROW_COUNT])
4141
{
4242
std::vector<ClusterNative>& clusterVector = clusters[slice][row];
4343
auto& lock = locks[slice][row];
4444
while (lock.test_and_set(std::memory_order_acquire)) {
4545
}
46-
auto& cluster = decompressTrackStore(clustersCompressed, offset, slice, row, pad, time, clusterVector);
46+
// Note the return type is ClusterNative, not auto&, since a different thread might append another cluster, and the vector expansion can change the cluster pointer, so the cluster reference might be invalid
47+
// TODO: A new version that might use a plain array + counter to fill the clusters should change this and the function return type to auto&
48+
ClusterNative retVal = decompressTrackStore(clustersCompressed, offset, slice, row, pad, time, clusterVector);
4749
lock.clear(std::memory_order_release);
48-
return cluster;
50+
return retVal;
4951
}
5052

5153
template <typename... Args>

0 commit comments

Comments
 (0)