Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Switch the event handling in the MC to libevent.
authorMatthieu Volat <mazhe@alkumuna.eu>
Tue, 29 Nov 2016 11:21:46 +0000 (12:21 +0100)
committerdegomme <augustin.degomme@unibas.ch>
Tue, 29 Nov 2016 11:33:30 +0000 (12:33 +0100)
This is a good alternative to provide a clean socket/signal
handling, which allows to finaly enable the MC on FreeBSD too. The
downside is that now libevent>=2 is necessary to build the model
checker.

Thanks to degomme@ for the mentoring ;)

CMakeLists.txt
src/mc/ModelChecker.cpp
src/mc/ModelChecker.hpp
tools/cmake/DefinePackages.cmake
tools/cmake/Modules/FindLibdw.cmake
tools/cmake/Modules/FindLibevent.cmake [new file with mode: 0644]

index dba5f6c..8c0e04c 100644 (file)
@@ -335,7 +335,7 @@ else()
   set(HAVE_THREAD_LOCAL_STORAGE 0)
 endif()
 
-if(enable_model-checking AND NOT "${CMAKE_SYSTEM}" MATCHES "Linux")
+if(enable_model-checking AND NOT "${CMAKE_SYSTEM}" MATCHES "Linux|FreeBSD")
   message(WARNING "Support for model-checking has not been enabled on ${CMAKE_SYSTEM}: disabling it")
   set(enable_model-checking FALSE)
 endif()
@@ -371,7 +371,7 @@ if(HAVE_LIBUNWIND)
     # So let's comply and link against the System framework
     SET(SIMGRID_DEP "${SIMGRID_DEP} -lSystem")
   endif()
-  if("${CMAKE_SYSTEM}" MATCHES "Linux")
+  if("${CMAKE_SYSTEM}" MATCHES "Linux|FreeBSD")
     set(SIMGRID_DEP "${SIMGRID_DEP} -lunwind-ptrace")
     # This supposes that the host machine is either an AMD or a X86.
     # This is deeply wrong, and should be fixed by manually loading -lunwind-PLAT (FIXME)
@@ -388,10 +388,11 @@ else()
 endif()
 
 if(enable_model-checking)
-  SET(HAVE_MC 1)
-  
-  include(FindLibdw)  
-  SET(SIMGRID_DEP "${SIMGRID_DEP} -ldw")
+  find_package(Libdw REQUIRED)
+  find_package(Libevent REQUIRED)
+  include_directories(${LIBDW_INCLUDE_DIRS} ${LIBEVENT_INCLUDE_DIRS})
+  set(SIMGRID_DEP "${SIMGRID_DEP} ${LIBEVENT_LIBRARIES} ${LIBDW_LIBRARIES}")
+  set(HAVE_MC 1)
 else()
   SET(HAVE_MC 0)  
   set(HAVE_MMALLOC 0)
index f0f149f..af0c666 100644 (file)
@@ -6,11 +6,9 @@
 
 #include <cassert>
 
-#include <poll.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <sys/socket.h>
-#include <sys/signalfd.h>
 #include <sys/ptrace.h>
 
 #include <memory>
@@ -46,14 +44,13 @@ using simgrid::mc::remote;
 # define WAITPID_CHECKED_FLAGS 0
 #endif
 
-// Hardcoded index for now:
-#define SOCKET_FD_INDEX 0
-#define SIGNAL_FD_INDEX 1
-
 namespace simgrid {
 namespace mc {
 
 ModelChecker::ModelChecker(std::unique_ptr<Process> process) :
+  base_(nullptr),
+  socket_event_(nullptr),
+  signal_event_(nullptr),
   page_store_(500),
   process_(std::move(process)),
   parent_snapshot_(nullptr)
@@ -61,37 +58,34 @@ ModelChecker::ModelChecker(std::unique_ptr<Process> process) :
 
 }
 
-ModelChecker::~ModelChecker() {}
+ModelChecker::~ModelChecker() {
+  if (socket_event_ != nullptr)
+    event_free(socket_event_);
+  if (signal_event_ != nullptr)
+    event_free(signal_event_);
+  if (base_ != nullptr)
+    event_base_free(base_);
+}
 
 void ModelChecker::start()
 {
   const pid_t pid = process_->pid();
 
-  // Block SIGCHLD (this will be handled with accept/signalfd):
-  sigset_t set;
-  sigemptyset(&set);
-  sigaddset(&set, SIGCHLD);
-  if (sigprocmask(SIG_BLOCK, &set, nullptr) == -1)
-    throw simgrid::xbt::errno_error();
-
-  sigset_t full_set;
-  sigfillset(&full_set);
-
-  // Prepare data for poll:
-
-  struct pollfd* socket_pollfd = &fds_[SOCKET_FD_INDEX];
-  socket_pollfd->fd = process_->getChannel().getSocket();
-  socket_pollfd->events = POLLIN;
-  socket_pollfd->revents = 0;
-
-  int signal_fd = signalfd(-1, &set, 0);
-  if (signal_fd == -1)
-    throw simgrid::xbt::errno_error();
-
-  struct pollfd* signalfd_pollfd = &fds_[SIGNAL_FD_INDEX];
-  signalfd_pollfd->fd = signal_fd;
-  signalfd_pollfd->events = POLLIN;
-  signalfd_pollfd->revents = 0;
+  base_ = event_base_new();
+  event_callback_fn event_callback = [](evutil_socket_t fd, short events, void *arg)
+  {
+    ((ModelChecker *)arg)->handle_events(fd, events);
+  };
+  socket_event_ = event_new(base_,
+                            process_->getChannel().getSocket(),
+                            EV_READ|EV_PERSIST,
+                            event_callback, this);
+  event_add(socket_event_, NULL);
+  signal_event_ = event_new(base_,
+                            SIGCHLD,
+                            EV_SIGNAL|EV_PERSIST,
+                            event_callback, this);
+  event_add(signal_event_, NULL);
 
   XBT_DEBUG("Waiting for the model-checked process");
   int status;
@@ -315,72 +309,29 @@ void ModelChecker::exit(int status)
   ::exit(status);
 }
 
-bool ModelChecker::handle_events()
+void ModelChecker::handle_events(int fd, short events)
 {
-  char buffer[MC_MESSAGE_LENGTH];
-  struct pollfd* socket_pollfd = &fds_[SOCKET_FD_INDEX];
-  struct pollfd* signalfd_pollfd = &fds_[SIGNAL_FD_INDEX];
-
-  while(poll(fds_, 2, -1) == -1) {
-    switch(errno) {
-    case EINTR:
-      continue;
-    default:
+  if (events == EV_READ) {
+    char buffer[MC_MESSAGE_LENGTH];
+    ssize_t size = process_->getChannel().receive(buffer, sizeof(buffer), false);
+    if (size == -1 && errno != EAGAIN)
       throw simgrid::xbt::errno_error();
+    if (!handle_message(buffer, size)) {
+      event_base_loopbreak(base_);
     }
   }
-
-  if (socket_pollfd->revents) {
-    if (socket_pollfd->revents & POLLIN) {
-      ssize_t size = process_->getChannel().receive(buffer, sizeof(buffer), false);
-      if (size == -1 && errno != EAGAIN)
-        throw simgrid::xbt::errno_error();
-      return handle_message(buffer, size);
-    }
-    if (socket_pollfd->revents & POLLERR)
-      throw_socket_error(socket_pollfd->fd);
-    if (socket_pollfd->revents & POLLHUP)
-      xbt_die("Socket hang up?");
+  else if (events == EV_SIGNAL) {
+    on_signal(fd);
   }
-
-  if (signalfd_pollfd->revents) {
-    if (signalfd_pollfd->revents & POLLIN) {
-      this->handle_signals();
-      return true;
-    }
-    if (signalfd_pollfd->revents & POLLERR)
-      throw_socket_error(signalfd_pollfd->fd);
-    if (signalfd_pollfd->revents & POLLHUP)
-      xbt_die("Signalfd hang up?");
+  else {
+    xbt_die("Unexpected event");
   }
-
-  return true;
 }
 
 void ModelChecker::loop()
 {
-  while (this->process().running())
-    this->handle_events();
-}
-
-void ModelChecker::handle_signals()
-{
-  struct signalfd_siginfo info;
-  struct pollfd* signalfd_pollfd = &fds_[SIGNAL_FD_INDEX];
-  while (1) {
-    ssize_t size = read(signalfd_pollfd->fd, &info, sizeof(info));
-    if (size == -1) {
-      if (errno == EINTR)
-        continue;
-      else
-        throw simgrid::xbt::errno_error();
-    } else if (size != sizeof(info))
-        return throw std::runtime_error(
-          "Bad communication with model-checked application");
-    else
-      break;
-  }
-  this->on_signal(&info);
+  if (this->process().running())
+    event_base_dispatch(base_);
 }
 
 void ModelChecker::handle_waitpid()
@@ -437,9 +388,9 @@ void ModelChecker::handle_waitpid()
   }
 }
 
-void ModelChecker::on_signal(const struct signalfd_siginfo* info)
+void ModelChecker::on_signal(int signo)
 {
-  switch(info->ssi_signo) {
+  switch(signo) {
   case SIGCHLD:
     this->handle_waitpid();
     break;
@@ -451,9 +402,8 @@ void ModelChecker::on_signal(const struct signalfd_siginfo* info)
 void ModelChecker::wait_client(simgrid::mc::Process& process)
 {
   this->resume(process);
-  while (this->process().running())
-    if (!this->handle_events())
-      return;
+  if (this->process().running())
+    event_base_dispatch(base_);
 }
 
 void ModelChecker::handle_simcall(Transition const& transition)
@@ -465,9 +415,8 @@ void ModelChecker::handle_simcall(Transition const& transition)
   m.value = transition.argument;
   this->process_->getChannel().send(m);
   this->process_->clear_cache();
-  while (this->process_->running())
-    if (!this->handle_events())
-      return;
+  if (this->process_->running())
+    event_base_dispatch(base_);
 }
 
 bool ModelChecker::checkDeadlock()
index 0e7ed9d..a1138ce 100644 (file)
@@ -9,12 +9,12 @@
 
 #include <sys/types.h>
 
-#include <poll.h>
-
 #include <memory>
 #include <set>
 #include <string>
 
+#include <event2/event.h>
+
 #include <simgrid_config.h>
 #include <xbt/base.h>
 #include <sys/types.h>
@@ -31,7 +31,8 @@ namespace mc {
 /** State of the model-checker (global variables for the model checker)
  */
 class ModelChecker {
-  struct pollfd fds_[2];
+  struct event_base *base_;
+  struct event *socket_event_, *signal_event_;
   /** String pool for host names */
   // TODO, use std::set with heterogeneous comparison lookup (C++14)?
   std::set<std::string> hostnames_;
@@ -70,7 +71,7 @@ public:
   void shutdown();
   void resume(simgrid::mc::Process& process);
   void loop();
-  bool handle_events();
+  void handle_events(int fd, short events);
   void wait_client(simgrid::mc::Process& process);
   void handle_simcall(Transition const& transition);
   void wait_for_requests()
@@ -87,9 +88,8 @@ public:
 private:
   void setup_ignore();
   bool handle_message(char* buffer, ssize_t size);
-  void handle_signals();
   void handle_waitpid();
-  void on_signal(const struct signalfd_siginfo* info);
+  void on_signal(int signo);
 
 public:
   unsigned long visited_states = 0;
index f732463..6d4b7f2 100644 (file)
@@ -1007,6 +1007,7 @@ set(CMAKE_SOURCE_FILES
   tools/cmake/Modules/FindGraphviz.cmake
   tools/cmake/Modules/FindLibdw.cmake
   tools/cmake/Modules/FindLibunwind.cmake
+  tools/cmake/Modules/FindLibevent.cmake
   tools/cmake/Modules/FindLuaSimgrid.cmake
   tools/cmake/Modules/FindNS3.cmake
   tools/cmake/Modules/FindPAPI.cmake
index 77ffc47..9574bda 100644 (file)
@@ -1,53 +1,34 @@
-find_library(PATH_LIBDW_LIB
-  NAMES dw
+find_path(LIBDW_INCLUDE_DIR "elfutils/libdw.h"
   HINTS
   $ENV{SIMGRID_LIBDW_LIBRARY_PATH}
   $ENV{LD_LIBRARY_PATH}
   $ENV{LIBDW_LIBRARY_PATH}
-  PATH_SUFFIXES lib/ GnuWin32/lib
+  PATH_SUFFIXES include/ GnuWin32/include
   PATHS
   /opt
   /opt/local
   /opt/csw
   /sw
   /usr)
-
-find_path(PATH_LIBDW_H "elfutils/libdw.h"
+find_library(LIBDW_LIBRARY
+  NAMES dw
   HINTS
   $ENV{SIMGRID_LIBDW_LIBRARY_PATH}
   $ENV{LD_LIBRARY_PATH}
   $ENV{LIBDW_LIBRARY_PATH}
-  PATH_SUFFIXES include/ GnuWin32/include
+  PATH_SUFFIXES lib/ GnuWin32/lib
   PATHS
   /opt
   /opt/local
   /opt/csw
   /sw
   /usr)
+set(LIBDW_LIBRARIES "${LIBDW_LIBRARY}")
 
-message(STATUS "Looking for libdw.h")
-if(PATH_LIBDW_H)
-  message(STATUS "Looking for libdw.h - found")
-else()
-  message(STATUS "Looking for libdw.h - not found")
-endif()
-
-message(STATUS "Looking for libdw")
-if(PATH_LIBDW_LIB)
-  message(STATUS "Looking for libdw - found")
-else()
-  message(STATUS "Looking for libdw - not found")
-endif()
-
-if(PATH_LIBDW_LIB AND PATH_LIBDW_H)
-  string(REGEX REPLACE "/libdw.*[.]${LIB_EXE}$" "" PATH_LIBDW_LIB "${PATH_LIBDW_LIB}")
-  string(REGEX REPLACE "/libdw.h"               "" PATH_LIBDW_H   "${PATH_LIBDW_H}")
-
-  include_directories(${PATH_LIBDW_H})
-  link_directories(${PATH_LIBDW_LIB})
-else()
-  message(FATAL_ERROR "Please either install the libdw-dev package (or equivalent) or turn off the model-checking option of SimGrid.")
-endif()
-
-mark_as_advanced(PATH_LIBDW_H)
-mark_as_advanced(PATH_LIBDW_LIB)
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(
+  Libdw
+  DEFAULT_MSG
+  LIBDW_LIBRARIES
+  LIBDW_INCLUDE_DIR)
+mark_as_advanced(LIBDW_INCLUDE_DIR LIBDW_LIBRARIES)
diff --git a/tools/cmake/Modules/FindLibevent.cmake b/tools/cmake/Modules/FindLibevent.cmake
new file mode 100644 (file)
index 0000000..c553995
--- /dev/null
@@ -0,0 +1,12 @@
+find_path(LIBEVENT_INCLUDE_DIR event2/event.h)
+find_library(LIBEVENT_LIBRARY NAMES event)
+find_library(LIBEVENT_THREADS_LIBRARY NAMES event_pthreads)
+set(LIBEVENT_LIBRARIES "${LIBEVENT_LIBRARY}")
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(
+    Libevent
+    DEFAULT_MSG
+    LIBEVENT_LIBRARIES
+    LIBEVENT_INCLUDE_DIR)
+mark_as_advanced(LIBEVENT_INCLUDE_DIR LIBEVENT_LIBRARIES)