Avoid resetting detached thread-local states.

In rare chance it can happen that some threads can end in between `CleanUpDetachedTls()` and `ForEachTls` when resetting the states.

PiperOrigin-RevId: 899651655
diff --git a/centipede/sancov_state.cc b/centipede/sancov_state.cc
index 19570d6..784793c 100644
--- a/centipede/sancov_state.cc
+++ b/centipede/sancov_state.cc
@@ -176,6 +176,7 @@
   // TODO(xinhaoyuan): Consider refactoring the list operations into class
   // methods instead of duplicating them.
   ThreadLocalSancovState *detached_tls = new ThreadLocalSancovState(tls);
+  detached_tls->detached = true;
   auto* old_list = sancov_state->detached_tls_list;
   detached_tls->next = old_list;
   sancov_state->detached_tls_list = detached_tls;
@@ -309,6 +310,7 @@
 void CleanUpSancovTls() {
   sancov_state->CleanUpDetachedTls();
   sancov_state->ForEachTls([](ThreadLocalSancovState& tls) {
+    if (tls.detached) return;
     if (sancov_state->flags.path_level != 0) {
       tls.path_ring_buffer.Reset(sancov_state->flags.path_level);
     }
diff --git a/centipede/sancov_state.h b/centipede/sancov_state.h
index 85407e3..5ff8d27 100644
--- a/centipede/sancov_state.h
+++ b/centipede/sancov_state.h
@@ -101,6 +101,9 @@
   // Whether the thread should be traced for execution feedback.
   bool traced;
 
+  // Whether the thread state is detached, i.e. the thread has ended.
+  bool detached;
+
   // Paths are thread-local, so we maintain the current bounded path here.
   // We allow paths of up to 100, controlled at run-time via the "path_level".
   static constexpr uint64_t kBoundedPathLength = 100;