drawinglayer/source/primitive2d/BufferedDecompositionFlusher.cxx | 13 ++++++++++ 1 file changed, 13 insertions(+)
New commits: commit 6bdf3b5eb9f61b9fc48026d59d37442fce9df392 Author: Noel Grandin <[email protected]> AuthorDate: Sun Feb 1 12:35:26 2026 +0200 Commit: Noel Grandin <[email protected]> CommitDate: Sun Feb 1 13:40:23 2026 +0100 fix deadlock seen on ubsan build Change-Id: I57996c0df31b435ef6680cc19ff224c5e6b028ac Reviewed-on: https://gerrit.libreoffice.org/c/core/+/198483 Tested-by: Jenkins Reviewed-by: Noel Grandin <[email protected]> diff --git a/drawinglayer/source/primitive2d/BufferedDecompositionFlusher.cxx b/drawinglayer/source/primitive2d/BufferedDecompositionFlusher.cxx index c84fbf7fb6d7..efc5fc5a633f 100644 --- a/drawinglayer/source/primitive2d/BufferedDecompositionFlusher.cxx +++ b/drawinglayer/source/primitive2d/BufferedDecompositionFlusher.cxx @@ -130,6 +130,7 @@ void SAL_CALL BufferedDecompositionFlusher::run() auto aNow = std::chrono::steady_clock::now(); std::vector<rtl::Reference<BufferedDecompositionPrimitive2D>> aRemoved1; std::vector<rtl::Reference<BufferedDecompositionGroupPrimitive2D>> aRemoved2; + std::vector<rtl::Reference<BasePrimitive2D>> aDelayRelease; { std::unique_lock l1(maMutex); // exit if we have been shutdown @@ -146,7 +147,10 @@ void SAL_CALL BufferedDecompositionFlusher::run() it = maRegistered1.erase(it); } else + { + aDelayRelease.push_back(std::move(xPrimitive)); ++it; + } } for (auto it = maRegistered2.begin(); it != maRegistered2.end();) { @@ -159,9 +163,18 @@ void SAL_CALL BufferedDecompositionFlusher::run() it = maRegistered2.erase(it); } else + { + aDelayRelease.push_back(std::move(xPrimitive)); ++it; + } } } + // There is a very very small window where, if : + // This-thread: we create a strong reference from a weak reference inside the loop + // Another-thread: releases the second last strong reference to the the object + // This-thread: we clear the reference, which triggers object destruction, which tries to call back + // into BufferedDecompositionFlusher and then deadlocks because the mutex is already acquired. + aDelayRelease.clear(); { // some parts of skia do not take kindly to being accessed from multiple threads
