Pass shmem size explicitly instead querying. Querying the size can be hard on some platforms. This replaces the switch flag :shmem: with the size flag :shmem_size_mb=: PiperOrigin-RevId: 963688253
diff --git a/centipede/centipede_callbacks.cc b/centipede/centipede_callbacks.cc index 961e935..6a3afa5 100644 --- a/centipede/centipede_callbacks.cc +++ b/centipede/centipede_callbacks.cc
@@ -399,8 +399,9 @@ } std::vector<std::string> env_diff = env_.env_diff_for_binaries; env_diff.push_back(ConstructRunnerFlags( - absl::StrCat(":shmem:test=", env_.test_name, ":arg1=", - inputs_blobseq_.path(), ":arg2=", outputs_blobseq_.path(), + absl::StrCat(":shmem_size_mb=", env_.shmem_size_mb, + ":test=", env_.test_name, ":arg1=", inputs_blobseq_.path(), + ":arg2=", outputs_blobseq_.path(), ":failure_description_path=", failure_description_path_, ":failure_signature_path=", failure_signature_path_, persistent_mode_server == nullptr
diff --git a/centipede/engine_worker.cc b/centipede/engine_worker.cc index 3c95801..2bba71b 100644 --- a/centipede/engine_worker.cc +++ b/centipede/engine_worker.cc
@@ -241,6 +241,7 @@ "persistent_mode_socket="; // TODO: Use better flag names when // standardizing the protocol. constexpr std::string_view kWorkerCrossOverLevel = "crossover_level="; +constexpr std::string_view kWorkerShmemSizeMbFlagHeader = "shmem_size_mb="; struct WorkerState { std::atomic<bool> has_failure_output = false; @@ -407,28 +408,44 @@ LogLnSync{}); } +size_t GetShmemSize() { + static auto result = []() -> size_t { + const char* shmem_size_mb_str = GetWorkerFlag(kWorkerShmemSizeMbFlagHeader); + if (shmem_size_mb_str != nullptr) { + const int parsed = + atoi(shmem_size_mb_str); // NOLINT: can't use strto64, etc. + if (parsed < 0) return 0; + return static_cast<size_t>(parsed) << 20; + } + return 0; + }(); + return result; +} + BlobSequence* GetInputsBlobSequence() { static auto result = []() -> BlobSequence* { - if (!HasWorkerSwitchFlag("shmem")) { + const size_t shmem_size = GetShmemSize(); + if (shmem_size == 0) { return nullptr; } const char* input_path = GetWorkerFlag(kWorkerInputsBlobSequencePathFlagHeader); WorkerCheck(input_path != nullptr, "inputs blob sequence is missing"); - return new SharedMemoryBlobSequence(input_path); + return new SharedMemoryBlobSequence(input_path, shmem_size); }(); return result; } BlobSequence* GetOutputsBlobSequence() { static auto result = []() -> BlobSequence* { - if (!HasWorkerSwitchFlag("shmem")) { + const size_t shmem_size = GetShmemSize(); + if (shmem_size == 0) { return nullptr; } const char* output_path = GetWorkerFlag(kWorkerOutputsBlobSequencePathFlagHeader); WorkerCheck(output_path != nullptr, "outputs blob sequence is missing"); - return new SharedMemoryBlobSequence(output_path); + return new SharedMemoryBlobSequence(output_path, shmem_size); }(); return result; }
diff --git a/centipede/minimize_crash.cc b/centipede/minimize_crash.cc index 0e12382..4399dcb 100644 --- a/centipede/minimize_crash.cc +++ b/centipede/minimize_crash.cc
@@ -143,6 +143,7 @@ auto callbacks = scoped_callback.callbacks(); FUZZTEST_LOG(INFO) << "MinimizeCrash: trying the original crashy input"; + CreateLocalDirRemovedAtExit(TemporaryLocalDirPath()); BatchResult batch_result; ByteArray original_crashy_input(crashy_input.begin(), crashy_input.end()); @@ -163,6 +164,7 @@ ThreadPool threads{static_cast<int>(env.num_threads)}; for (size_t i = 0; i < env.num_threads; ++i) { threads.Schedule([&env, &callbacks_factory, &queue, &stop_condition]() { + CreateLocalDirRemovedAtExit(TemporaryLocalDirPath()); MinimizeCrash(env, callbacks_factory, queue, stop_condition); }); }
diff --git a/centipede/runner.cc b/centipede/runner.cc index 40e4f39..847f6d8 100644 --- a/centipede/runner.cc +++ b/centipede/runner.cc
@@ -902,9 +902,10 @@ // This means, the binary is standalone with its own main(), and we need to // report the coverage now. if (!state->centipede_runner_main_executed && - flag_helper.HasFlag(":shmem:")) { + state->run_time_flags.shmem_size_mb != 0) { PostProcessSancov(); // TODO(xinhaoyuan): do we know our exit status? - SharedMemoryBlobSequence outputs_blobseq(sancov_state->arg2); + SharedMemoryBlobSequence outputs_blobseq( + sancov_state->arg2, state->run_time_flags.shmem_size_mb << 20); StartSendingOutputsToEngine(outputs_blobseq); FinishSendingOutputsToEngine(outputs_blobseq); } @@ -987,9 +988,9 @@ return EXIT_SUCCESS; } -// If HasFlag(:shmem:), state->arg1 and state->arg2 are the names -// of in/out shared memory locations. -// Read inputs and write outputs via shared memory. +// If state->run_time_flags.shmem_size_mb is non-zero, state->arg1 and +// state->arg2 are the names of in/out shared memory locations. Read inputs and +// write outputs via shared memory. // // Default: Execute ReadOneInputExecuteItAndDumpCoverage() for all inputs.// // @@ -1013,10 +1014,12 @@ } // Inputs / outputs from shmem. - if (state->flag_helper.HasFlag(":shmem:")) { + if (state->run_time_flags.shmem_size_mb != 0) { if (!sancov_state->arg1 || !sancov_state->arg2) return EXIT_FAILURE; - SharedMemoryBlobSequence inputs_blobseq(sancov_state->arg1); - SharedMemoryBlobSequence outputs_blobseq(sancov_state->arg2); + SharedMemoryBlobSequence inputs_blobseq( + sancov_state->arg1, state->run_time_flags.shmem_size_mb << 20); + SharedMemoryBlobSequence outputs_blobseq( + sancov_state->arg2, state->run_time_flags.shmem_size_mb << 20); // Persistent mode loop. if (state->persistent_mode_socket > 0) { return HandlePersistentMode(callbacks, inputs_blobseq, outputs_blobseq);
diff --git a/centipede/runner.h b/centipede/runner.h index 5ddc3b3..2a5d23b 100644 --- a/centipede/runner.h +++ b/centipede/runner.h
@@ -19,6 +19,7 @@ #include <time.h> #include <atomic> +#include <cstddef> #include <cstdint> #include "./centipede/byte_array_mutator.h" @@ -38,6 +39,7 @@ uint64_t ignore_timeout_reports : 1; uint64_t max_len; std::atomic<uint64_t> stack_limit_kb; + size_t shmem_size_mb; }; // One global object of this type is created by the runner at start up. @@ -72,6 +74,8 @@ flag_helper.HasFlag(":ignore_timeout_reports:"), /*max_len=*/flag_helper.HasIntFlag(":max_len=", 4000), /*stack_limit_kb=*/flag_helper.HasIntFlag(":stack_limit_kb=", 0), + /*shmem_size_mb=*/ + static_cast<size_t>(flag_helper.HasIntFlag(":shmem_size_mb=", 0)), }; // The path to a file where the runner may write the description of failure.
diff --git a/centipede/shared_memory_blob_sequence.cc b/centipede/shared_memory_blob_sequence.cc index 3a24126..51415df 100644 --- a/centipede/shared_memory_blob_sequence.cc +++ b/centipede/shared_memory_blob_sequence.cc
@@ -135,7 +135,10 @@ MmapData(); } -SharedMemoryBlobSequence::SharedMemoryBlobSequence(const char *path) { +SharedMemoryBlobSequence::SharedMemoryBlobSequence(const char* path, + size_t size) { + ErrorOnFailure(size < sizeof(Blob::size), "Size too small"); + size_ = size; // This is a quick way to tell shm-allocated paths from memfd paths without // requiring the caller to specify. if (strncmp(path, "/proc/", 6) == 0) { @@ -146,9 +149,6 @@ ErrorOnFailure(fd_ < 0, "open() failed"); strncpy(path_, path, PATH_MAX); ErrorOnFailure(path_[PATH_MAX - 1] != 0, "path length exceeds PATH_MAX."); - struct stat statbuf = {}; - ErrorOnFailure(fstat(fd_, &statbuf), "fstat() failed"); - size_ = statbuf.st_size; MmapData(); }
diff --git a/centipede/shared_memory_blob_sequence.h b/centipede/shared_memory_blob_sequence.h index fc69c10..b5d781e 100644 --- a/centipede/shared_memory_blob_sequence.h +++ b/centipede/shared_memory_blob_sequence.h
@@ -134,7 +134,7 @@ // // void Child() { // // Open an existing blob sequence. -// SharedMemoryBlobSequence child("/foo"); +// SharedMemoryBlobSequence child("/foo", 1000); // // // Read the data written by parent. // while (true) { @@ -155,9 +155,9 @@ // memfd_create(2). SharedMemoryBlobSequence(const char *name, size_t size, bool use_posix_shmem); - // Opens an existing shared blob sequence with the file `path`. + // Opens an existing shared blob sequence with the file `path` and `size`. // Aborts on any failure. - explicit SharedMemoryBlobSequence(const char *path); + SharedMemoryBlobSequence(const char* path, size_t size); // Releases all resources. ~SharedMemoryBlobSequence();
diff --git a/centipede/shared_memory_blob_sequence_test.cc b/centipede/shared_memory_blob_sequence_test.cc index 2b9f557..f5dd4fc 100644 --- a/centipede/shared_memory_blob_sequence_test.cc +++ b/centipede/shared_memory_blob_sequence_test.cc
@@ -112,7 +112,7 @@ EXPECT_TRUE(parent.Write(BlobFromVec(kTestData2, 456))); // Child created. - SharedMemoryBlobSequence child(parent.path()); + SharedMemoryBlobSequence child(parent.path(), 1000); // Child reads data. auto blob1 = child.Read(); EXPECT_EQ(kTestData1, Vec(blob1)); @@ -141,14 +141,14 @@ for (int iter = 0; iter < kNumIters; iter++) { SharedMemoryBlobSequence parent(ShmemName().c_str(), kBlobSize, GetParam()); parent.Write(BlobFromVec({1, 2, 3})); - SharedMemoryBlobSequence child(parent.path()); + SharedMemoryBlobSequence child(parent.path(), kBlobSize); EXPECT_EQ(child.Read().size, 3); } // Create a parent blob, then create and destroy lots of child blobs. SharedMemoryBlobSequence parent(ShmemName().c_str(), kBlobSize, GetParam()); parent.Write(BlobFromVec({1, 2, 3, 4})); for (int iter = 0; iter < kNumIters; iter++) { - SharedMemoryBlobSequence child(parent.path()); + SharedMemoryBlobSequence child(parent.path(), kBlobSize); EXPECT_EQ(child.Read().size, 4); } }