@@ -994,6 +994,10 @@ class OPENTELEMETRY_LOCAL_SYMBOL OtlpFileSystemBackend : public OtlpFileAppender
994994 {
995995 if (file_)
996996 {
997+ {
998+ std::lock_guard<std::mutex> waker_guard{file_->background_thread_waker_lock };
999+ file_->is_shutdown .store (true , std::memory_order_release);
1000+ }
9971001 file_->background_thread_waker_cv .notify_all ();
9981002 std::unique_ptr<std::thread> background_flush_thread;
9991003 {
@@ -1133,7 +1137,10 @@ class OPENTELEMETRY_LOCAL_SYMBOL OtlpFileSystemBackend : public OtlpFileAppender
11331137
11341138 bool Shutdown (std::chrono::microseconds timeout) noexcept override
11351139 {
1136- file_->is_shutdown .store (true , std::memory_order_release);
1140+ {
1141+ std::lock_guard<std::mutex> waker_guard{file_->background_thread_waker_lock };
1142+ file_->is_shutdown .store (true , std::memory_order_release);
1143+ }
11371144
11381145 bool result = ForceFlush (timeout);
11391146 return result;
@@ -1482,21 +1489,26 @@ class OPENTELEMETRY_LOCAL_SYMBOL OtlpFileSystemBackend : public OtlpFileAppender
14821489 break ;
14831490 }
14841491
1485- if (concurrency_file->is_shutdown .load (std::memory_order_acquire))
1486- {
1487- break ;
1488- }
1489-
14901492#ifdef ENABLE_THREAD_INSTRUMENTATION_PREVIEW
14911493 if (thread_instrumentation != nullptr )
14921494 {
14931495 thread_instrumentation->BeforeWait ();
14941496 }
14951497#endif /* ENABLE_THREAD_INSTRUMENTATION_PREVIEW */
14961498
1499+ bool is_shutdown = false ;
14971500 {
14981501 std::unique_lock<std::mutex> lk (concurrency_file->background_thread_waker_lock );
1499- concurrency_file->background_thread_waker_cv .wait_for (lk, flush_interval);
1502+ // Even though is_shutdown is atomic, the lock guarantees that either a change to
1503+ // is_shutdown will be observed, or background_thread_waker_cv will see the notification
1504+ // at shutdown. It is important to set is_shutdown prior to `wait_for` rather than
1505+ // as part of a condition in `wait_for` so that a shutdown while the thread is in
1506+ // `wait_for` will still call `std::fflush` below.
1507+ is_shutdown = concurrency_file->is_shutdown .load (std::memory_order_acquire);
1508+ if (!is_shutdown)
1509+ {
1510+ concurrency_file->background_thread_waker_cv .wait_for (lk, flush_interval);
1511+ }
15001512 }
15011513
15021514#ifdef ENABLE_THREAD_INSTRUMENTATION_PREVIEW
@@ -1506,6 +1518,11 @@ class OPENTELEMETRY_LOCAL_SYMBOL OtlpFileSystemBackend : public OtlpFileAppender
15061518 }
15071519#endif /* ENABLE_THREAD_INSTRUMENTATION_PREVIEW */
15081520
1521+ if (is_shutdown)
1522+ {
1523+ break ;
1524+ }
1525+
15091526 {
15101527 std::size_t current_record_count =
15111528 concurrency_file->record_count .load (std::memory_order_acquire);
0 commit comments