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);
   }
 }