Skip to content

Commit 59dff64

Browse files
xinhaoyuancopybara-github
authored andcommitted
Add --ignore_timeout_reports to use timeout without reporting errors. #Centipede
This is to be used when timeout reports are noisy. In this change, timeouts are almost hidden from the view of the controller (except that the controller can see an incomplete batch execution result). Having more visibility in controller is desired but not done yet. PiperOrigin-RevId: 740033429
1 parent b8e43c7 commit 59dff64

File tree

7 files changed

+74
-17
lines changed

7 files changed

+74
-17
lines changed

centipede/centipede_callbacks.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,9 @@ std::string CentipedeCallbacks::ConstructRunnerFlags(
131131
absl::StrCat("stack_limit_kb=", env_.stack_limit_kb),
132132
absl::StrCat("crossover_level=", env_.crossover_level),
133133
};
134+
if (env_.ignore_timeout_reports) {
135+
flags.emplace_back("ignore_timeout_reports");
136+
}
134137
if (!disable_coverage) {
135138
flags.emplace_back(absl::StrCat("path_level=", env_.path_level));
136139
if (env_.use_pc_features) flags.emplace_back("use_pc_features");

centipede/environment.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ struct Environment {
6868
size_t timeout_per_input = 60;
6969
size_t timeout_per_batch = 0;
7070
absl::Duration force_abort_timeout = absl::Minutes(15);
71+
bool ignore_timeout_reports = false;
7172
absl::Time stop_at = absl::InfiniteFuture();
7273
bool fork_server = true;
7374
bool full_sync = false;

centipede/environment_flags.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,9 @@ ABSL_FLAG(
166166
"hangs (e.g., during stacktrace dumps). The default value is ",
167167
Environment::Default().force_abort_timeout,
168168
"; use 'inf' to disable."));
169+
ABSL_FLAG(bool, ignore_timeout_reports,
170+
Environment::Default().ignore_timeout_reports,
171+
"If set, will ignore reporting timeouts as errors.");
169172
ABSL_FLAG(absl::Time, stop_at, Environment::Default().stop_at,
170173
"Stop fuzzing in all shards (--total_shards) at approximately this "
171174
"time in ISO-8601/RFC-3339 format, e.g. 2023-04-06T23:35:02Z. "
@@ -472,6 +475,7 @@ Environment CreateEnvironmentFromFlags(const std::vector<std::string> &argv) {
472475
/*timeout_per_input=*/absl::GetFlag(FLAGS_timeout_per_input),
473476
/*timeout_per_batch=*/absl::GetFlag(FLAGS_timeout_per_batch),
474477
/*force_abort_timeout=*/absl::GetFlag(FLAGS_force_abort_timeout),
478+
/*ignore_timeout_reports=*/absl::GetFlag(FLAGS_ignore_timeout_reports),
475479
/*stop_at=*/
476480
GetStopAtTime(absl::GetFlag(FLAGS_stop_at),
477481
absl::GetFlag(FLAGS_stop_after)),

centipede/runner.cc

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -240,32 +240,36 @@ static void CheckWatchdogLimits() {
240240
const char *units;
241241
uint64_t value;
242242
uint64_t limit;
243+
bool ignore_report;
243244
const char *failure;
244245
};
245246
const uint64_t input_start_time = state.input_start_time;
246247
const uint64_t batch_start_time = state.batch_start_time;
247248
if (input_start_time == 0 || batch_start_time == 0) return;
248249
const Resource resources[] = {
249250
{Resource{
250-
/*what =*/"Per-input timeout",
251-
/*units =*/"sec",
252-
/*value =*/curr_time - input_start_time,
253-
/*limit =*/state.run_time_flags.timeout_per_input,
254-
/*failure =*/kExecutionFailurePerInputTimeout.data(),
251+
/*what=*/"Per-input timeout",
252+
/*units=*/"sec",
253+
/*value=*/curr_time - input_start_time,
254+
/*limit=*/state.run_time_flags.timeout_per_input,
255+
/*ignore_report=*/state.run_time_flags.ignore_timeout_reports != 0,
256+
/*failure=*/kExecutionFailurePerInputTimeout.data(),
255257
}},
256258
{Resource{
257-
/*what =*/"Per-batch timeout",
258-
/*units =*/"sec",
259-
/*value =*/curr_time - batch_start_time,
260-
/*limit =*/state.run_time_flags.timeout_per_batch,
261-
/*failure =*/kExecutionFailurePerBatchTimeout.data(),
259+
/*what=*/"Per-batch timeout",
260+
/*units=*/"sec",
261+
/*value=*/curr_time - batch_start_time,
262+
/*limit=*/state.run_time_flags.timeout_per_batch,
263+
/*ignore_report=*/state.run_time_flags.ignore_timeout_reports != 0,
264+
/*failure=*/kExecutionFailurePerBatchTimeout.data(),
262265
}},
263266
{Resource{
264-
/*what =*/"RSS limit",
265-
/*units =*/"MB",
266-
/*value =*/GetPeakRSSMb(),
267-
/*limit =*/state.run_time_flags.rss_limit_mb,
268-
/*failure =*/kExecutionFailureRssLimitExceeded.data(),
267+
/*what=*/"RSS limit",
268+
/*units=*/"MB",
269+
/*value=*/GetPeakRSSMb(),
270+
/*limit=*/state.run_time_flags.rss_limit_mb,
271+
/*ignore_report=*/false,
272+
/*failure=*/kExecutionFailureRssLimitExceeded.data(),
269273
}},
270274
};
271275
for (const auto &resource : resources) {
@@ -275,6 +279,15 @@ static void CheckWatchdogLimits() {
275279
// `RunOneInput()` after all the work is done.
276280
static std::atomic<bool> already_handling_failure = false;
277281
if (!already_handling_failure.exchange(true)) {
282+
if (resource.ignore_report) {
283+
fprintf(stderr,
284+
"========= %s exceeded: %" PRIu64 " > %" PRIu64
285+
" (%s); exiting without reporting as an error\n",
286+
resource.what, resource.value, resource.limit,
287+
resource.units);
288+
std::_Exit(0);
289+
// should not return here.
290+
}
278291
fprintf(stderr,
279292
"========= %s exceeded: %" PRIu64 " > %" PRIu64
280293
" (%s); exiting\n",

centipede/runner.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ struct RunTimeFlags {
7272
std::atomic<uint64_t> rss_limit_mb;
7373
uint64_t crossover_level;
7474
uint64_t skip_seen_features : 1;
75+
uint64_t ignore_timeout_reports : 1;
7576
};
7677

7778
// One such object is created in runner's TLS.
@@ -177,7 +178,9 @@ struct GlobalRunnerState {
177178
/*stack_limit_kb=*/HasIntFlag(":stack_limit_kb=", 0),
178179
/*rss_limit_mb=*/HasIntFlag(":rss_limit_mb=", 0),
179180
/*crossover_level=*/HasIntFlag(":crossover_level=", 50),
180-
/*skip_seen_features=*/HasFlag(":skip_seen_features:")};
181+
/*skip_seen_features=*/HasFlag(":skip_seen_features:"),
182+
/*ignore_timeout_reports=*/HasFlag(":ignore_timeout_reports:"),
183+
};
181184

182185
// Returns true iff `flag` is present.
183186
// Typical usage: pass ":some_flag:", i.e. the flag name surrounded with ':'.

centipede/testing/centipede_main_test.sh

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,37 @@ test_pcpair_features() {
176176
centipede::assert_regex_in_file "end-fuzz.*pair: [^0]" "${LOG}"
177177
}
178178

179+
test_timeouts() {
180+
FUNC="${FUNCNAME[0]}"
181+
WD="${TEST_TMPDIR}/${FUNC}/WD"
182+
CORPUS="${TEST_TMPDIR}/${FUNC}/corpus"
183+
LOG="${TEST_TMPDIR}/${FUNC}/log"
184+
185+
centipede::ensure_empty_dir "${WD}"
186+
centipede::ensure_empty_dir "${CORPUS}"
187+
echo -n "slo" >"${CORPUS}"/input
188+
189+
echo "============ ${FUNC}: fuzz with --timeout_per_input"
190+
test_fuzz --workdir="${WD}" --corpus_dir="${CORPUS}" --num_runs=0 --timeout_per_input=2 | tee "${LOG}"
191+
centipede::assert_regex_in_file "Failure.*: per-input-timeout-exceeded" "${LOG}"
192+
centipede::assert_regex_in_file "end-fuzz:.*crash: 1" "${LOG}"
193+
194+
centipede::ensure_empty_dir "${WD}"
195+
centipede::ensure_empty_dir "${CORPUS}"
196+
echo -n "slo" >"${CORPUS}"/input
197+
198+
echo "============ ${FUNC}: fuzz with --timeout_per_input --ignore_timeout_reports"
199+
test_fuzz --workdir="${WD}" --corpus_dir="${CORPUS}" --num_runs=0 --timeout_per_input=2 --ignore_timeout_reports | tee "${LOG}"
200+
centipede::assert_regex_not_in_file "Failure.*: per-input-timeout-exceeded" "${LOG}"
201+
centipede::assert_regex_not_in_file "end-fuzz:.*crash: 1" "${LOG}"
202+
}
203+
204+
179205
centipede::test_crashing_target abort_test_fuzz "foo" "AbOrT" "I AM ABOUT TO ABORT"
180206
test_debug_symbols
181207
test_dictionary
182208
test_for_each_blob
183209
test_pcpair_features
210+
test_timeouts
184211

185212
echo "PASS"

centipede/testing/runner_test.sh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,11 +107,17 @@ CENTIPEDE_RUNNER_FLAGS=":rss_limit_mb=8192:" $target "${oom}" # must pass
107107

108108
echo ======== Check timeout
109109
CENTIPEDE_RUNNER_FLAGS=":timeout_per_input=567:" "${target}" \
110-
2>&1 | grep "timeout_per_input:.567"
110+
2>&1 | grep "timeout_per_input: 567"
111111

112112
CENTIPEDE_RUNNER_FLAGS=":timeout_per_input=2:" "${target}" "${slo}" \
113113
2>&1 | grep "Per-input timeout exceeded"
114114

115+
{
116+
CENTIPEDE_RUNNER_FLAGS=":ignore_timeout_reports:timeout_per_input=2:" "${target}" "${slo}";
117+
echo "$?" > "${TEST_TMPDIR}/ignore_timeout_reports_exit_code";
118+
} 2>&1 | grep "Per-input timeout exceeded" | grep "exiting without reporting as an error"
119+
((`cat "${TEST_TMPDIR}/ignore_timeout_reports_exit_code"` == 0))
120+
115121
echo ======== Check stack limit check with stack_limit
116122
CENTIPEDE_RUNNER_FLAGS=":use_pc_features:stack_limit_kb=200:" "${target}" "${stk}" # must pass
117123

0 commit comments

Comments
 (0)