From 182a62894d25db7ec5205dbb0c9aaf220dac0aa1 Mon Sep 17 00:00:00 2001 From: aadi-joshi Date: Sun, 2 Aug 2026 14:55:36 +0530 Subject: [PATCH] fuzz: dump progress every 30s so long campaigns survive kills --- fuzz/harness.c | 56 ++++++++++++++++++++++++++++++++++++++++----- scripts/run-fuzz.sh | 4 +++- 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/fuzz/harness.c b/fuzz/harness.c index 94fc4fc..1e17a2f 100644 --- a/fuzz/harness.c +++ b/fuzz/harness.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -123,16 +124,45 @@ static double now_secs(void) { return (double)ts.tv_sec + (double)ts.tv_nsec / 1e9; } +static volatile sig_atomic_t stop_requested = 0; +static void on_signal(int sig) { + (void)sig; + stop_requested = 1; +} + +static void write_progress(const char *path, const struct stats *stats, double elapsed, + uint64_t seed, int final_flag) { + FILE *fp; + if (!path || !path[0]) return; + fp = fopen(path, "w"); + if (!fp) return; + fprintf(fp, + "{\"executions\":%" PRIu64 ",\"divergences\":%" PRIu64 + ",\"first_token_reject\":%" PRIu64 + ",\"seconds\":%.6f,\"exec_per_sec\":%.2f,\"seed\":%" PRIu64 + ",\"final\":%s}\n", + stats->executions, stats->divergences, stats->first_token_reject, elapsed, + stats->executions / (elapsed > 0 ? elapsed : 1.0), seed, + final_flag ? "true" : "false"); + fflush(fp); + fclose(fp); +} + int main(int argc, char **argv) { double duration = 60.0; const char *seed_path = NULL; + const char *progress_path = NULL; uint64_t seed = (uint64_t)time(NULL) ^ (uint64_t)getpid(); struct stats stats = { 0 }; char buffer[256]; double start; double end; + double last_progress = 0.0; int index; + signal(SIGTERM, on_signal); + signal(SIGINT, on_signal); + for (index = 1; index < argc; ++index) { if (strcmp(argv[index], "--seconds") == 0 && index + 1 < argc) { duration = strtod(argv[++index], NULL); @@ -140,14 +170,20 @@ int main(int argc, char **argv) { seed = strtoull(argv[++index], NULL, 10); } else if (strcmp(argv[index], "--seed-corpus") == 0 && index + 1 < argc) { seed_path = argv[++index]; + } else if (strcmp(argv[index], "--progress-file") == 0 && index + 1 < argc) { + progress_path = argv[++index]; } else { - fprintf(stderr, "usage: %s [--seconds N] [--seed N] [--seed-corpus PATH]\n", argv[0]); + fprintf(stderr, + "usage: %s [--seconds N] [--seed N] [--seed-corpus PATH] " + "[--progress-file PATH]\n", + argv[0]); return 2; } } start = now_secs(); end = start + duration; + last_progress = start; /* Seed corpus first (once each). */ if (seed_path) { @@ -168,24 +204,32 @@ int main(int argc, char **argv) { } } - while (now_secs() < end) { + while (!stop_requested && now_secs() < end) { + double now; generate(buffer, sizeof(buffer), seed + stats.executions); ++stats.executions; if (is_first_token_reject(buffer)) ++stats.first_token_reject; if (compare_one(buffer) != 0) { ++stats.divergences; fprintf(stderr, "DIVERGENCE: %s\n", buffer); - /* keep going; count all */ + } + now = now_secs(); + if (progress_path && (now - last_progress) >= 30.0) { + write_progress(progress_path, &stats, now - start, seed, 0); + last_progress = now; } } { double elapsed = now_secs() - start; + write_progress(progress_path, &stats, elapsed, seed, 1); printf("{\"executions\":%" PRIu64 ",\"divergences\":%" PRIu64 ",\"first_token_reject\":%" PRIu64 - ",\"seconds\":%.6f,\"exec_per_sec\":%.2f,\"seed\":%" PRIu64 "}\n", - stats.executions, stats.divergences, stats.first_token_reject, - elapsed, stats.executions / (elapsed > 0 ? elapsed : 1.0), seed); + ",\"seconds\":%.6f,\"exec_per_sec\":%.2f,\"seed\":%" PRIu64 + ",\"stopped_early\":%s}\n", + stats.executions, stats.divergences, stats.first_token_reject, elapsed, + stats.executions / (elapsed > 0 ? elapsed : 1.0), seed, + stop_requested ? "true" : "false"); return stats.divergences == 0 ? 0 : 1; } } diff --git a/scripts/run-fuzz.sh b/scripts/run-fuzz.sh index ba66e41..0ed94fc 100644 --- a/scripts/run-fuzz.sh +++ b/scripts/run-fuzz.sh @@ -51,8 +51,10 @@ print(len(lines)) PY RESULT="$WORK/result-$MODE.json" +PROGRESS="$WORK/progress-$MODE.json" set +e -"$WORK/harness" --seconds "$SECONDS_ARG" --seed-corpus "$SEED" >"$RESULT" +"$WORK/harness" --seconds "$SECONDS_ARG" --seed-corpus "$SEED" \ + --progress-file "$PROGRESS" >"$RESULT" STATUS=$? set -e END_UTC="$(date -u +%Y-%m-%dT%H:%M:%SZ)"