Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
MC: Reap all zombie childs to avoid them to accumulate
[simgrid.git] / src / mc / remote / AppSide.cpp
index 9efa308..b66d7a1 100644 (file)
 #include "src/kernel/actor/SimcallObserver.hpp"
 #include "src/mc/mc_base.hpp"
 #include "src/mc/mc_config.hpp"
+#include "src/mc/mc_environ.h"
+#if SIMGRID_HAVE_STATEFUL_MC
 #include "src/mc/sosp/RemoteProcessMemory.hpp"
+#endif
 #if HAVE_SMPI
 #include "src/smpi/include/private.hpp"
 #endif
@@ -38,16 +41,18 @@ namespace simgrid::mc {
 
 std::unique_ptr<AppSide> AppSide::instance_;
 
-AppSide* AppSide::initialize()
+AppSide* AppSide::get()
 {
-  if (not std::getenv(MC_ENV_SOCKET_FD)) // We are not in MC mode: don't initialize the MC world
+  // Only initialize the MC world once
+  if (instance_ != nullptr)
+    return instance_.get();
+
+  if (std::getenv(MC_ENV_SOCKET_FD) == nullptr) // We are not in MC mode: don't initialize the MC world
     return nullptr;
 
-  // Do not break if we are called multiple times:
-  if (instance_)
-    return instance_.get();
+  XBT_DEBUG("Initialize the MC world. %s=%s", MC_ENV_NEED_PTRACE, std::getenv(MC_ENV_NEED_PTRACE));
 
-  simgrid::mc::model_checking_mode = ModelCheckingMode::APP_SIDE;
+  simgrid::mc::set_model_checking_mode(ModelCheckingMode::APP_SIDE);
 
   setvbuf(stdout, nullptr, _IOLBF, 0);
 
@@ -56,17 +61,10 @@ AppSide* AppSide::initialize()
   int fd             = xbt_str_parse_int(fd_env, "Not a number in variable '" MC_ENV_SOCKET_FD "'");
   XBT_DEBUG("Model-checked application found socket FD %i", fd);
 
-  // Check the socket type/validity:
-  int type;
-  socklen_t socklen = sizeof(type);
-  xbt_assert(getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &socklen) == 0, "Could not check socket type");
-  xbt_assert(type == SOCK_SEQPACKET, "Unexpected socket type %i", type);
-  XBT_DEBUG("Model-checked application found expected socket type");
-
   instance_ = std::make_unique<simgrid::mc::AppSide>(fd);
 
   // Wait for the model-checker:
-  if (getenv("MC_NEED_PTRACE") != nullptr) {
+  if (getenv(MC_ENV_NEED_PTRACE) != nullptr) {
     errno = 0;
 #if defined __linux__
     ptrace(PTRACE_TRACEME, 0, nullptr, nullptr);
@@ -154,19 +152,31 @@ void AppSide::handle_finalize(const s_mc_message_int_t* msg) const
 }
 void AppSide::handle_fork(const s_mc_message_int_t* msg)
 {
-  int pid = fork();
+  int status;
+  int pid;
+  /* Reap any zombie child, saving its status for later use in AppSide::handle_wait_child() */
+  while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
+    child_statuses_[pid] = status;
+
+  pid = fork();
   xbt_assert(pid >= 0, "Could not fork application sub-process: %s.", strerror(errno));
 
   if (pid == 0) { // Child
-    int sock = socket(AF_LOCAL, SOCK_SEQPACKET | SOCK_CLOEXEC, 0);
+    int sock = socket(AF_UNIX,
+#ifdef __APPLE__
+                      SOCK_STREAM, /* Mac OSX does not have AF_UNIX + SOCK_SEQPACKET, even if that's faster*/
+#else
+                      SOCK_SEQPACKET,
+#endif
+                      0);
 
     struct sockaddr_un addr = {};
-    addr.sun_family         = AF_LOCAL;
-    snprintf(addr.sun_path, 64, "/tmp/simgrid-mc-%lu", msg->value);
+    addr.sun_family         = AF_UNIX;
+    snprintf(addr.sun_path, 64, "/tmp/simgrid-mc-%lu", static_cast<unsigned long>(msg->value));
     auto addr_size = offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path);
 
     xbt_assert(connect(sock, (struct sockaddr*)&addr, addr_size) >= 0,
-               "Cannot connect to Checker on /tmp/simgrid-mc-%lu: %s.", msg->value, strerror(errno));
+               "Cannot connect to Checker on %s: %s.", addr.sun_path, strerror(errno));
 
     channel_.reset_socket(sock);
 
@@ -174,13 +184,20 @@ void AppSide::handle_fork(const s_mc_message_int_t* msg)
     answer.type               = MessageType::FORK_REPLY;
     answer.value              = getpid();
     xbt_assert(channel_.send(answer) == 0, "Could not send response to WAIT_CHILD_REPLY: %s", strerror(errno));
+  } else {
+    XBT_VERB("App %d forks subprocess %d.", getpid(), pid);
   }
 }
 void AppSide::handle_wait_child(const s_mc_message_int_t* msg)
 {
   int status;
   errno = 0;
-  waitpid(msg->value, &status, 0);
+  if (auto search = child_statuses_.find(msg->value); search != child_statuses_.end()) {
+    status = search->second;
+    child_statuses_.erase(search); // We only need this info once
+  } else {
+    waitpid(msg->value, &status, 0);
+  }
   xbt_assert(errno == 0, "Cannot wait on behalf of the checker: %s.", strerror(errno));
 
   s_mc_message_int_t answer = {};
@@ -190,7 +207,7 @@ void AppSide::handle_wait_child(const s_mc_message_int_t* msg)
 }
 void AppSide::handle_need_meminfo()
 {
-#if SIMGRID_HAVE_MC
+#if SIMGRID_HAVE_STATEFUL_MC
   this->need_memory_info_                  = true;
   s_mc_message_need_meminfo_reply_t answer = {};
   answer.type                              = MessageType::NEED_MEMINFO_REPLY;
@@ -369,7 +386,7 @@ void AppSide::ignore_memory(void* addr, std::size_t size) const
   if (not MC_is_active() || not need_memory_info_)
     return;
 
-#if SIMGRID_HAVE_MC
+#if SIMGRID_HAVE_STATEFUL_MC
   s_mc_message_ignore_memory_t message = {};
   message.type = MessageType::IGNORE_MEMORY;
   message.addr = (std::uintptr_t)addr;
@@ -385,7 +402,7 @@ void AppSide::ignore_heap(void* address, std::size_t size) const
   if (not MC_is_active() || not need_memory_info_)
     return;
 
-#if SIMGRID_HAVE_MC
+#if SIMGRID_HAVE_STATEFUL_MC
   const s_xbt_mheap_t* heap = mmalloc_get_current_heap();
 
   s_mc_message_ignore_heap_t message = {};
@@ -412,7 +429,7 @@ void AppSide::unignore_heap(void* address, std::size_t size) const
   if (not MC_is_active() || not need_memory_info_)
     return;
 
-#if SIMGRID_HAVE_MC
+#if SIMGRID_HAVE_STATEFUL_MC
   s_mc_message_ignore_memory_t message = {};
   message.type = MessageType::UNIGNORE_HEAP;
   message.addr = (std::uintptr_t)address;
@@ -430,7 +447,7 @@ void AppSide::declare_symbol(const char* name, int* value) const
     return;
   }
 
-#if SIMGRID_HAVE_MC
+#if SIMGRID_HAVE_STATEFUL_MC
   s_mc_message_register_symbol_t message = {};
   message.type = MessageType::REGISTER_SYMBOL;
   xbt_assert(strlen(name) + 1 <= message.name.size(), "Symbol is too long");
@@ -449,12 +466,13 @@ void AppSide::declare_symbol(const char* name, int* value) const
  *  when we analyze/compare the content of the heap so it must be told where
  *  they are with this function.
  */
+#if HAVE_UCONTEXT_H /* Apple don't want us to use ucontexts */
 void AppSide::declare_stack(void* stack, size_t size, ucontext_t* context) const
 {
   if (not MC_is_active() || not need_memory_info_)
     return;
 
-#if SIMGRID_HAVE_MC
+#if SIMGRID_HAVE_STATEFUL_MC
   const s_xbt_mheap_t* heap = mmalloc_get_current_heap();
 
   s_stack_region_t region = {};
@@ -471,4 +489,6 @@ void AppSide::declare_stack(void* stack, size_t size, ucontext_t* context) const
   xbt_die("Cannot really call declare_stack() in non-SIMGRID_MC mode.");
 #endif
 }
+#endif
+
 } // namespace simgrid::mc