diff --git a/centipede/centipede_callbacks.cc b/centipede/centipede_callbacks.cc index 90c583e20..38c84d6cd 100644 --- a/centipede/centipede_callbacks.cc +++ b/centipede/centipede_callbacks.cc @@ -401,7 +401,8 @@ CentipedeCallbacks::GetOrCreateCommandContextForBinary( std::vector env_diff = env_.env_diff_for_binaries; env_diff.push_back(ConstructRunnerFlags( absl::StrCat( - ":shmem:test=", EscapeEngineFlag(env_.test_name), + ":shmem_size_mb=", env_.shmem_size_mb, + ":test=", EscapeEngineFlag(env_.test_name), ":arg1=", EscapeEngineFlag(inputs_blobseq_.path()), ":arg2=", EscapeEngineFlag(outputs_blobseq_.path()), ":failure_description_path=", diff --git a/centipede/engine_worker.cc b/centipede/engine_worker.cc index a80697349..28228b080 100644 --- a/centipede/engine_worker.cc +++ b/centipede/engine_worker.cc @@ -199,6 +199,7 @@ constexpr std::string_view kWorkerPersistentModeSocketPathFlagHeader = // standardizing the protocol. constexpr std::string_view kWorkerCrossOverLevel = "crossover_level="; constexpr std::string_view kWorkerMinSeeds = "min_seeds="; +constexpr std::string_view kWorkerShmemSizeMbFlagHeader = "shmem_size_mb="; struct WorkerState { std::atomic has_failure_output = false; @@ -365,28 +366,39 @@ __attribute__((constructor(200))) void WorkerInitEarly() { LogLnSync{}); } +size_t GetShmemSize() { + static auto result = []() -> size_t { + const uint64_t shmem_size_mb = + GetWorkerFlags().GetIntFlag(kWorkerShmemSizeMbFlagHeader, 0); + return static_cast(shmem_size_mb) << 20; + }(); + return result; +} + BlobSequence* GetInputsBlobSequence() { static auto result = []() -> BlobSequence* { - if (!GetWorkerFlags().HasSwitchFlag("shmem")) { + const size_t shmem_size = GetShmemSize(); + if (shmem_size == 0) { return nullptr; } const char* input_path = GetWorkerFlags().GetStringFlag(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 (!GetWorkerFlags().HasSwitchFlag("shmem")) { + const size_t shmem_size = GetShmemSize(); + if (shmem_size == 0) { return nullptr; } const char* output_path = GetWorkerFlags().GetStringFlag( 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/runner.cc b/centipede/runner.cc index f50d6ae3c..c2d3eefd3 100644 --- a/centipede/runner.cc +++ b/centipede/runner.cc @@ -902,9 +902,10 @@ void GlobalRunnerState::OnTermination() { // 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.HasSwitchFlag("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); } @@ -988,9 +989,9 @@ static int HandlePersistentMode(RunnerCallbacks& callbacks, return EXIT_SUCCESS; } -// If HasSwitchFlag(: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.// // @@ -1015,10 +1016,12 @@ int RunnerMain(int argc, char** argv, RunnerCallbacks& callbacks) { } // Inputs / outputs from shmem. - if (state->flag_helper.HasSwitchFlag("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 7cdbe5a2f..b64f732a1 100644 --- a/centipede/runner.h +++ b/centipede/runner.h @@ -19,6 +19,7 @@ #include #include +#include #include #include "./centipede/byte_array_mutator.h" @@ -37,6 +38,7 @@ struct RunTimeFlags { uint64_t ignore_timeout_reports : 1; uint64_t max_len; std::atomic stack_limit_kb; + size_t shmem_size_mb; }; // One global object of this type is created by the runner at start up. @@ -70,6 +72,8 @@ struct GlobalRunnerState { flag_helper.HasSwitchFlag("ignore_timeout_reports"), /*max_len=*/flag_helper.GetIntFlag("max_len=", 4000), /*stack_limit_kb=*/flag_helper.GetIntFlag("stack_limit_kb=", 0), + /*shmem_size_mb=*/ + static_cast(flag_helper.GetIntFlag("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 3a2412649..51415df13 100644 --- a/centipede/shared_memory_blob_sequence.cc +++ b/centipede/shared_memory_blob_sequence.cc @@ -135,7 +135,10 @@ SharedMemoryBlobSequence::SharedMemoryBlobSequence(const char *name, 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 @@ SharedMemoryBlobSequence::SharedMemoryBlobSequence(const char *path) { 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 fc69c10dd..b5d781e3c 100644 --- a/centipede/shared_memory_blob_sequence.h +++ b/centipede/shared_memory_blob_sequence.h @@ -134,7 +134,7 @@ class BlobSequence { // // 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 @@ class SharedMemoryBlobSequence : public BlobSequence { // 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 2b9f55799..f5dd4fc45 100644 --- a/centipede/shared_memory_blob_sequence_test.cc +++ b/centipede/shared_memory_blob_sequence_test.cc @@ -112,7 +112,7 @@ TEST_P(SharedMemoryBlobSequenceTest, ParentChild) { 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 @@ TEST_P(SharedMemoryBlobSequenceTest, CheckForResourceLeaks) { 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); } }