Skip to content

Commit 867ecb3

Browse files
committed
executor: enable periodic leak checking
This commit enables the periodic execution of a leak checker within the executor. The leak checker will now run every 5000 program executions, but only after the corpus has been triaged and all executor processes are in an idle state. Fixes #4728.
1 parent 86341da commit 867ecb3

File tree

1 file changed

+50
-3
lines changed

1 file changed

+50
-3
lines changed

executor/executor_runner.h

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,6 @@ class Proc
197197
return;
198198
}
199199

200-
private:
201200
enum State : uint8 {
202201
// The process has just started.
203202
Started,
@@ -209,6 +208,43 @@ class Proc
209208
Executing,
210209
};
211210

211+
State GetState() const
212+
{
213+
return state_;
214+
}
215+
216+
void RunLeakChecker()
217+
{
218+
debug("proc %d: running leak checker\n", id_);
219+
int stdout_pipe[2];
220+
if (pipe(stdout_pipe))
221+
fail("leak checker pipe failed");
222+
223+
const char* argv[] = {bin_, "leak", nullptr};
224+
std::vector<std::pair<int, int>> fds = {
225+
{-1, STDIN_FILENO}, // We don't need an stdin pipe. No communication is done in the parent -> child direction.
226+
{stdout_pipe[1], STDOUT_FILENO},
227+
{stdout_pipe[1], STDERR_FILENO},
228+
};
229+
Subprocess leak_process(argv, fds);
230+
close(stdout_pipe[1]);
231+
232+
std::vector<uint8_t> output;
233+
for (;;) {
234+
const size_t kChunk = 1024;
235+
output.resize(output.size() + kChunk);
236+
ssize_t n = read(stdout_pipe[0], output.data() + output.size() - kChunk, kChunk);
237+
output.resize(output.size() - kChunk + std::max<ssize_t>(n, 0));
238+
if (n <= 0)
239+
break;
240+
}
241+
output.push_back(0);
242+
fprintf(stderr, "proc %d: leak checker output:\n%s\n", id_, (const char*)output.data());
243+
244+
close(stdout_pipe[0]);
245+
}
246+
247+
private:
212248
Connection& conn_;
213249
const char* const bin_;
214250
ProcIDPool& proc_id_pool_;
@@ -575,6 +611,7 @@ class Runner
575611
std::vector<std::string> leak_frames_;
576612
int restarting_ = 0;
577613
bool corpus_triaged_ = false;
614+
uint64 proc_counter_ = 0;
578615
ProcOpts proc_opts_{};
579616

580617
friend std::ostream& operator<<(std::ostream& ss, const Runner& runner)
@@ -623,9 +660,19 @@ class Runner
623660

624661
for (auto& proc : procs_) {
625662
proc->Ready(select, now, requests_.empty());
626-
if (!requests_.empty()) {
627-
if (proc->Execute(requests_.front()))
663+
constexpr uint64 kRunLeakCheckEvery = 5000;
664+
if (corpus_triaged_ && proc_counter_ && proc_counter_ % kRunLeakCheckEvery == 0) {
665+
if (std::all_of(procs_.begin(), procs_.end(), [](const auto& proc) {
666+
return proc->GetState() == Proc::State::Idle;
667+
})) {
668+
proc->RunLeakChecker();
669+
++proc_counter_;
670+
}
671+
} else if (!requests_.empty()) {
672+
if (proc->Execute(requests_.front())) {
628673
requests_.pop_front();
674+
++proc_counter_;
675+
}
629676
}
630677
}
631678

0 commit comments

Comments
 (0)