Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Better responsabilities splitup between CheckerSide and RemoteProcessMemory
authorMartin Quinson <martin.quinson@ens-rennes.fr>
Sun, 19 Mar 2023 14:57:19 +0000 (15:57 +0100)
committerMartin Quinson <martin.quinson@ens-rennes.fr>
Sun, 19 Mar 2023 15:02:31 +0000 (16:02 +0100)
src/mc/api/RemoteApp.cpp
src/mc/api/RemoteApp.hpp
src/mc/explo/Exploration.cpp
src/mc/remote/CheckerSide.cpp
src/mc/remote/CheckerSide.hpp
src/mc/sosp/RemoteProcessMemory.cpp
src/mc/sosp/RemoteProcessMemory.hpp

index 131aec5..df0c81f 100644 (file)
@@ -123,8 +123,7 @@ RemoteApp::RemoteApp(const std::vector<char*>& args)
   // Parent (model-checker):
   ::close(sockets[0]);
 
-  auto memory      = std::make_unique<simgrid::mc::RemoteProcessMemory>(pid);
-  checker_side_    = std::make_unique<simgrid::mc::CheckerSide>(sockets[1], std::move(memory));
+  checker_side_ = std::make_unique<simgrid::mc::CheckerSide>(sockets[1], pid);
 
   start();
 
@@ -144,7 +143,7 @@ void RemoteApp::start()
   int status;
 
   // The model-checked process SIGSTOP itself to signal it's ready:
-  const pid_t pid = get_remote_process_memory().pid();
+  const pid_t pid = checker_side_->get_pid();
 
   xbt_assert(waitpid(pid, &status, WAITPID_CHECKED_FLAGS) == pid && WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP,
              "Could not wait model-checked process");
@@ -292,7 +291,7 @@ void RemoteApp::wait_for_requests()
     throw xbt::errno_error();
   get_remote_process_memory().clear_cache();
 
-  if (this->get_remote_process_memory().running())
+  if (checker_side_->running())
     checker_side_->dispatch_events();
 }
 
@@ -300,12 +299,11 @@ void RemoteApp::shutdown()
 {
   XBT_DEBUG("Shutting down model-checker");
 
-  RemoteProcessMemory& process = get_remote_process_memory();
-  if (process.running()) {
+  if (checker_side_->running()) {
     XBT_DEBUG("Killing process");
     finalize_app(true);
-    kill(process.pid(), SIGKILL);
-    process.terminate();
+    kill(checker_side_->get_pid(), SIGKILL);
+    checker_side_->terminate();
   }
 }
 
@@ -318,7 +316,7 @@ Transition* RemoteApp::handle_simcall(aid_t aid, int times_considered, bool new_
   checker_side_->get_channel().send(m);
 
   get_remote_process_memory().clear_cache();
-  if (this->get_remote_process_memory().running())
+  if (checker_side_->running())
     checker_side_->dispatch_events(); // The app may send messages while processing the transition
 
   s_mc_message_simcall_execute_answer_t answer;
index 026353c..62758d5 100644 (file)
@@ -18,11 +18,11 @@ namespace simgrid::mc {
 
 /** High-level view of the verified application, from the model-checker POV
  *
- *  This is expected to become the interface used by model-checking
- *  algorithms to control the execution of the model-checked process
- *  and the exploration of the execution graph. Model-checking
- *  algorithms should be able to be written in high-level languages
- *  (e.g. Python) using bindings on this interface.
+ *  This is expected to become the interface used by model-checking algorithms to control the execution of
+ *  the application process during the exploration of the execution graph.
+ *
+ *  One day, this will allow parallel exploration, ie, the handling of several application processes (each encapsulated
+ * in a separate CheckerSide objects) that explore several parts of the exploration graph.
  */
 class XBT_PUBLIC RemoteApp {
 private:
index 2440c09..1dbe4c4 100644 (file)
@@ -91,7 +91,6 @@ void Exploration::report_crash(int status)
     get_remote_app().get_remote_process_memory().dump_stack();
   }
 
-  get_remote_app().get_remote_process_memory().terminate();
   system_exit(SIMGRID_MC_EXIT_PROGRAM_CRASH);
 }
 void Exploration::report_assertion_failure()
index 9d6df4d..1660265 100644 (file)
 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_checkerside, mc, "MC communication with the application");
 
 namespace simgrid::mc {
-CheckerSide::CheckerSide(int sockfd, std::unique_ptr<RemoteProcessMemory> memory)
-    : remote_memory_(std::move(memory)), channel_(sockfd)
+CheckerSide::CheckerSide(int sockfd, pid_t pid)
+    : remote_memory_(std::make_unique<simgrid::mc::RemoteProcessMemory>(pid))
+    , channel_(sockfd)
+    , running_(true)
+    , pid_(pid)
 {
   auto* base = event_base_new();
   base_.reset(base);
@@ -159,7 +162,7 @@ void CheckerSide::handle_waitpid()
   while ((pid = waitpid(-1, &status, WNOHANG)) != 0) {
     if (pid == -1) {
       if (errno == ECHILD) { // No more children:
-        xbt_assert(not get_remote_memory().running(), "Inconsistent state");
+        xbt_assert(not this->running(), "Inconsistent state");
         break;
       } else {
         XBT_ERROR("Could not wait for pid");
@@ -167,15 +170,17 @@ void CheckerSide::handle_waitpid()
       }
     }
 
-    if (pid == get_remote_memory().pid()) {
+    if (pid == get_pid()) {
       // From PTRACE_O_TRACEEXIT:
 #ifdef __linux__
       if (status >> 8 == (SIGTRAP | (PTRACE_EVENT_EXIT << 8))) {
         unsigned long eventmsg;
         xbt_assert(ptrace(PTRACE_GETEVENTMSG, pid, 0, &eventmsg) != -1, "Could not get exit status");
         status = static_cast<int>(eventmsg);
-        if (WIFSIGNALED(status))
+        if (WIFSIGNALED(status)) {
+          this->terminate();
           Exploration::get_instance()->report_crash(status);
+        }
       }
 #endif
 
@@ -192,10 +197,11 @@ void CheckerSide::handle_waitpid()
       }
 
       else if (WIFSIGNALED(status)) {
+        this->terminate();
         Exploration::get_instance()->report_crash(status);
       } else if (WIFEXITED(status)) {
         XBT_DEBUG("Child process is over");
-        get_remote_memory().terminate();
+        this->terminate();
       }
     }
   }
index 8f99b48..53f121c 100644 (file)
@@ -15,6 +15,8 @@
 
 namespace simgrid::mc {
 
+/* CheckerSide: All what the checker needs to interact with a given application process */
+
 class CheckerSide {
   std::unique_ptr<event_base, decltype(&event_base_free)> base_{nullptr, &event_base_free};
   std::unique_ptr<event, decltype(&event_free)> socket_event_{nullptr, &event_free};
@@ -22,23 +24,31 @@ class CheckerSide {
   std::unique_ptr<RemoteProcessMemory> remote_memory_;
   Channel channel_;
 
+  bool running_ = false;
+  pid_t pid_;
+
 public:
-  explicit CheckerSide(int sockfd, std::unique_ptr<RemoteProcessMemory> mem);
+  explicit CheckerSide(int sockfd, pid_t pid);
 
   // No copy:
   CheckerSide(CheckerSide const&) = delete;
   CheckerSide& operator=(CheckerSide const&) = delete;
   CheckerSide& operator=(CheckerSide&&) = delete;
 
+  /* Communicating with the application */
   Channel const& get_channel() const { return channel_; }
   Channel& get_channel() { return channel_; }
-  RemoteProcessMemory& get_remote_memory() { return *remote_memory_.get(); }
 
+  bool handle_message(const char* buffer, ssize_t size);
   void dispatch_events() const;
   void break_loop() const;
 
+  /* Interacting with the application process */
+  pid_t get_pid() const { return pid_; }
+  bool running() const { return running_; }
+  void terminate() { running_ = false; }
+  RemoteProcessMemory& get_remote_memory() { return *remote_memory_.get(); }
   void handle_waitpid();
-  bool handle_message(const char* buffer, ssize_t size);
 };
 
 } // namespace simgrid::mc
index 0051ddf..0a06fb4 100644 (file)
@@ -106,7 +106,7 @@ int open_vm(pid_t pid, int flags)
 
 // ***** RemoteProcessMemory
 
-RemoteProcessMemory::RemoteProcessMemory(pid_t pid) : AddressSpace(this), pid_(pid), running_(true) {}
+RemoteProcessMemory::RemoteProcessMemory(pid_t pid) : AddressSpace(this), pid_(pid) {}
 
 void RemoteProcessMemory::init(xbt_mheap_t mmalloc_default_mdp)
 {
index 40aef18..7b4dff5 100644 (file)
@@ -32,14 +32,14 @@ struct IgnoredHeapRegion {
   std::size_t size;
 };
 
-/** The Application's process memory, seen from the Checker perspective
+/** The Application's process memory, seen from the Checker perspective. This class is not needed if you don't need to
+ * introspect the application process.
  *
- *  Responsibilities:
- *
- *  - reading from the process memory (`AddressSpace`);
- *  - accessing the system state of the process (heap, …);
- *  - stack unwinding;
- *  - etc.
+ *  Responsabilities:
+ *    - reading from the process memory (`AddressSpace`);
+ *    - accessing the system state of the process (heap, …);
+ *    - stack unwinding;
+ *    - etc.
  */
 class RemoteProcessMemory final : public AddressSpace {
 private:
@@ -59,10 +59,6 @@ public:
   RemoteProcessMemory& operator=(RemoteProcessMemory const&) = delete;
   RemoteProcessMemory& operator=(RemoteProcessMemory&&)      = delete;
 
-  pid_t pid() const { return pid_; }
-  bool running() const { return running_; }
-  void terminate() { running_ = false; }
-
   /* ************* */
   /* Low-level API */
   /* ************* */
@@ -145,8 +141,7 @@ private:
   void refresh_heap();
   void refresh_malloc_info();
 
-  pid_t pid_    = -1;
-  bool running_ = false;
+  pid_t pid_ = -1;
   std::vector<xbt::VmMap> memory_map_;
   RemotePtr<void> maestro_stack_start_;
   RemotePtr<void> maestro_stack_end_;