Skip to content

Commit

Permalink
#Centipede Collect the coverage for thread calling OnThreadStop befor…
Browse files Browse the repository at this point in the history
…e the execution ends.

This is done by keeping detached copies of the coverage states on a separate list when calling OnThreadStop.

PiperOrigin-RevId: 578924831
  • Loading branch information
xinhaoyuan authored and copybara-github committed Nov 2, 2023
1 parent f375329 commit 2d7ebf0
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 4 deletions.
4 changes: 1 addition & 3 deletions centipede/puzzles/thread_uint32_cmp_1.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@
// We should be able to solve it w/o cmp features *or* w/o auto dictionary.
// RUN: Run && SolutionIs Fuzz
// RUN: Run --use_auto_dictionary=0 && SolutionIs Fuzz
// TODO(b/295378866): Centipede runner currently fails to collect dictionary
// entries from merged threads, so if we disable cmp features we can't crack
// this puzzle. Enable "Run --use_cmp_features=0 && SolutionIs Fuzz"
// RUN: Run --use_cmp_features=0 && SolutionIs Fuzz

#include <cstdint>
#include <cstdlib>
Expand Down
25 changes: 25 additions & 0 deletions centipede/runner.cc
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,18 @@ void ThreadLocalRunnerState::OnThreadStop() {
prev_tls->next = next_tls;
if (next_tls != nullptr) next_tls->prev = prev_tls;
}
tls.next = tls.prev = nullptr;
if (tls.ignore) return;
// Create a detached copy on heap and add it to detached_tls_list to
// collect its coverage later.
//
// TODO(xinhaoyuan): Consider refactoring the list operations into class
// methods instead of duplicating them.
ThreadLocalRunnerState *detached_tls = new ThreadLocalRunnerState(tls);
auto *old_list = state.detached_tls_list;
detached_tls->next = old_list;
state.detached_tls_list = detached_tls;
if (old_list != nullptr) old_list->prev = detached_tls;
}

static size_t GetPeakRSSMb() {
Expand Down Expand Up @@ -233,6 +245,16 @@ static void CheckWatchdogLimits() {
}
}

void GlobalRunnerState::CleanUpDetachedTls() {
LockGuard lock(tls_list_mu);
ThreadLocalRunnerState *it_next = nullptr;
for (auto *it = detached_tls_list; it; it = it_next) {
it_next = it->next;
delete it;
}
detached_tls_list = nullptr;
}

void GlobalRunnerState::StartWatchdogThread() {
if (state.run_time_flags.timeout_per_input == 0 &&
state.run_time_flags.timeout_per_batch == 0 &&
Expand Down Expand Up @@ -313,6 +335,7 @@ static void WriteFeaturesToFile(FILE *file, const feature_t *features,
__attribute__((noinline)) // so that we see it in profile.
static void
PrepareCoverage(bool full_clear) {
state.CleanUpDetachedTls();
if (state.run_time_flags.path_level != 0) {
state.ForEachTls([](ThreadLocalRunnerState &tls) {
tls.path_ring_buffer.Reset(state.run_time_flags.path_level);
Expand Down Expand Up @@ -929,6 +952,8 @@ GlobalRunnerState::~GlobalRunnerState() {
StartSendingOutputsToEngine(outputs_blobseq);
FinishSendingOutputsToEngine(outputs_blobseq);
}
// Always clean up detached TLSs to avoid leakage.
CleanUpDetachedTls();
}

// If HasFlag(:shmem:), state.arg1 and state.arg2 are the names
Expand Down
11 changes: 10 additions & 1 deletion centipede/runner.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ struct ThreadLocalRunnerState {
CmpTrace<0, 64> cmp_traceN;

// Set this to true if the thread needs to be ignored in ForEachTLS.
// It should be always false if the state is in the global detached_tls_list.
bool ignore;
};

Expand Down Expand Up @@ -191,7 +192,9 @@ struct GlobalRunnerState {

// Doubly linked list of TLSs of all live threads.
ThreadLocalRunnerState *tls_list;
pthread_mutex_t tls_list_mu; // Guards tls_list.
// Doubly linked list of detached TLSs.
ThreadLocalRunnerState *detached_tls_list;
pthread_mutex_t tls_list_mu; // Guards tls_list and detached_tls_list.
// Iterates all TLS objects under tls_list_mu, except those with `ignore` set.
// Calls `callback()` on every TLS.
template <typename Callback>
Expand All @@ -200,8 +203,14 @@ struct GlobalRunnerState {
for (auto *it = tls_list; it; it = it->next) {
if (!it->ignore) callback(*it);
}
for (auto *it = detached_tls_list; it; it = it->next) {
callback(*it);
}
}

// Reclaims all TLSs in detached_tls_list and cleans up the list.
void CleanUpDetachedTls();

// Computed by DlInfo().
// Usually, the main object is the executable binary containing main()
// and most of the executable code (we assume that the target is
Expand Down

0 comments on commit 2d7ebf0

Please sign in to comment.