Skip to content

Commit 195136d

Browse files
facontidavideclaude
andcommitted
Fix TSAN race: add mutex protection for file_stream access
The flush() method was accessing file_stream without synchronization while the writer thread was also accessing it. This adds a file_mutex to protect all file_stream operations in both flush() and writerLoop(). Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent 1c0e2d9 commit 195136d

File tree

1 file changed

+15
-10
lines changed

1 file changed

+15
-10
lines changed

src/loggers/bt_file_logger_v2.cpp

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ int64_t ToUsec(Duration ts)
1919
struct detail::FileLogger2Private
2020
{
2121
std::ofstream file_stream;
22+
std::mutex file_mutex; // Protects file_stream access from multiple threads
2223

2324
Duration first_timestamp = {};
2425

@@ -132,6 +133,7 @@ void FileLogger2::callback(Duration timestamp, const TreeNode& node,
132133

133134
void FileLogger2::flush()
134135
{
136+
const std::scoped_lock lock(_p->file_mutex);
135137
_p->file_stream.flush();
136138
}
137139

@@ -159,18 +161,21 @@ void FileLogger2::writerLoop()
159161
// simple way to pop all the transitions from _p->transitions_queue into transitions
160162
std::swap(transitions, _p->transitions_queue);
161163
}
162-
while(!transitions.empty())
163164
{
164-
const auto trans = transitions.front();
165-
std::array<char, 9> write_buffer{};
166-
std::memcpy(write_buffer.data(), &trans.timestamp_usec, 6);
167-
std::memcpy(write_buffer.data() + 6, &trans.node_uid, 2);
168-
std::memcpy(write_buffer.data() + 8, &trans.status, 1);
169-
170-
_p->file_stream.write(write_buffer.data(), 9);
171-
transitions.pop_front();
165+
const std::scoped_lock file_lock(_p->file_mutex);
166+
while(!transitions.empty())
167+
{
168+
const auto trans = transitions.front();
169+
std::array<char, 9> write_buffer{};
170+
std::memcpy(write_buffer.data(), &trans.timestamp_usec, 6);
171+
std::memcpy(write_buffer.data() + 6, &trans.node_uid, 2);
172+
std::memcpy(write_buffer.data() + 8, &trans.status, 1);
173+
174+
_p->file_stream.write(write_buffer.data(), 9);
175+
transitions.pop_front();
176+
}
177+
_p->file_stream.flush();
172178
}
173-
_p->file_stream.flush();
174179
}
175180
}
176181

0 commit comments

Comments
 (0)