From e4b7fdf98923fe3a2a5dd3521a057a848c7963c5 Mon Sep 17 00:00:00 2001
From: Marco Clemencic <marco.clemencic@cern.ch>
Date: Thu, 6 Apr 2023 10:33:18 +0200
Subject: [PATCH] Fix race condition in periodic auto flush implementation

use std::promise/future instead of misusing std::condition_variable
---
 Kernel/FileSummaryRecord/src/mod/FSRSink.cpp | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/Kernel/FileSummaryRecord/src/mod/FSRSink.cpp b/Kernel/FileSummaryRecord/src/mod/FSRSink.cpp
index 75193a99287..b9dbd32ed68 100644
--- a/Kernel/FileSummaryRecord/src/mod/FSRSink.cpp
+++ b/Kernel/FileSummaryRecord/src/mod/FSRSink.cpp
@@ -28,10 +28,10 @@ namespace Gaudi::Utils {
 #include <TFile.h>
 #include <algorithm>
 #include <chrono>
-#include <condition_variable>
 #include <filesystem>
 #include <fmt/format.h>
 #include <fstream>
+#include <future>
 #include <iterator>
 #include <list>
 #include <map>
@@ -121,10 +121,9 @@ namespace LHCb::FSR {
       return Service::start().andThen( [&] {
         // enable periodic output file flush if requested
         if ( m_autoFlushPeriod.value() != 0. && !m_outputFile.empty() ) {
-          m_flushThread = std::thread{[this]() {
+          m_flushThread = std::thread{[this, flushStop = m_flushThreadStop.get_future()]() {
             using namespace std::chrono_literals;
-            std::unique_lock lk( m_flushCondMutex );
-            while ( m_flushCond.wait_for( lk, m_autoFlushPeriod.value() * 1s ) == std::cv_status::timeout ) {
+            while ( flushStop.wait_for( m_autoFlushPeriod.value() * 1s ) == std::future_status::timeout ) {
               writeOutputFile( collect() );
             }
           }};
@@ -199,7 +198,7 @@ namespace LHCb::FSR {
     StatusCode finalize() override {
       if ( auto incSvc = service<IIncidentSvc>( "IncidentSvc" ) ) { incSvc->removeListener( this ); }
 
-      m_flushCond.notify_all();                             // tell the flush thread we are stopping
+      m_flushThreadStop.set_value();                        // tell the flush thread we are stopping
       if ( m_flushThread.joinable() ) m_flushThread.join(); // and wait that it exits
 
       nlohmann::json fsr = collect();
@@ -261,9 +260,8 @@ namespace LHCb::FSR {
     std::vector<OutputFile>       m_outputFiles;
     std::list<nlohmann::json>     m_inputsFSRs;
 
-    std::thread             m_flushThread;
-    std::condition_variable m_flushCond;
-    std::mutex              m_flushCondMutex;
+    std::thread        m_flushThread;
+    std::promise<void> m_flushThreadStop;
   };
   DECLARE_COMPONENT( Sink )
 } // namespace LHCb::FSR
-- 
GitLab