Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[mc] Move Server in simgrid::mc
[simgrid.git] / src / mc / mc_server.cpp
diff --git a/src/mc/mc_server.cpp b/src/mc/mc_server.cpp
deleted file mode 100644 (file)
index db325d2..0000000
+++ /dev/null
@@ -1,383 +0,0 @@
-/* Copyright (c) 2015. The SimGrid Team.
- * All rights reserved.                                                     */
-
-/* This program is free software; you can redistribute it and/or modify it
- * under the terms of the license (GNU LGPL) which comes with this package. */
-
-#include <memory>
-#include <system_error>
-
-#include <poll.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/socket.h>
-#include <sys/signalfd.h>
-#include <sys/ptrace.h>
-
-#include <xbt/log.h>
-#include <xbt/automaton.h>
-#include <xbt/automaton.hpp>
-
-#include "ModelChecker.hpp"
-#include "mc_protocol.h"
-#include "mc_server.h"
-#include "mc_private.h"
-#include "mc_ignore.h"
-#include "mcer_ignore.h"
-#include "mc_exit.h"
-#include "src/mc/mc_liveness.h"
-
-using simgrid::mc::remote;
-
-extern "C" {
-
-XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_server, mc, "MC server logic");
-
-// HArdcoded index for now:
-#define SOCKET_FD_INDEX 0
-#define SIGNAL_FD_INDEX 1
-
-mc_server_t mc_server;
-
-s_mc_server::s_mc_server(pid_t pid_, int socket_)
-  : pid(pid_), socket(socket_) {}
-
-void s_mc_server::start()
-{
-  // Block SIGCHLD (this will be handled with accept/signalfd):
-  sigset_t set;
-  sigemptyset(&set);
-  sigaddset(&set, SIGCHLD);
-  if (sigprocmask(SIG_BLOCK, &set, NULL) == -1)
-    throw std::system_error(errno, std::system_category());
-
-  sigset_t full_set;
-  sigfillset(&full_set);
-
-  // Prepare data for poll:
-
-  struct pollfd* socket_pollfd = &fds[SOCKET_FD_INDEX];
-  socket_pollfd->fd = socket;
-  socket_pollfd->events = POLLIN;
-  socket_pollfd->revents = 0;
-
-  int signal_fd = signalfd(-1, &set, 0);
-  if (signal_fd == -1)
-    throw std::system_error(errno, std::system_category());
-
-  struct pollfd* signalfd_pollfd = &fds[SIGNAL_FD_INDEX];
-  signalfd_pollfd->fd = signal_fd;
-  signalfd_pollfd->events = POLLIN;
-  signalfd_pollfd->revents = 0;
-
-  XBT_DEBUG("Waiting for the model-checked process");
-  int status;
-
-  // The model-checked process SIGSTOP itself to signal it's ready:
-  pid_t res = waitpid(pid, &status, __WALL);
-  if (res < 0 || !WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP)
-    xbt_die("Could not wait model-checked process");
-
-  // The model-checked process is ready, we can read its memory layout:
-  MC_init_model_checker(pid, socket);
-
-  ptrace(PTRACE_SETOPTIONS, pid, nullptr, PTRACE_O_TRACEEXIT);
-  ptrace(PTRACE_CONT, pid, 0, 0);
-}
-
-void s_mc_server::shutdown()
-{
-  XBT_DEBUG("Shuting down model-checker");
-
-  simgrid::mc::Process* process = &mc_model_checker->process();
-  int status = process->status();
-  if (process->running()) {
-    XBT_DEBUG("Killing process");
-    kill(process->pid(), SIGTERM);
-    if (waitpid(process->pid(), &status, 0) == -1)
-      throw std::system_error(errno, std::system_category());
-    // TODO, handle the case when the process does not want to die with a timeout
-    process->terminate(status);
-  }
-}
-
-void s_mc_server::exit()
-{
-  // Finished:
-  int status = mc_model_checker->process().status();
-  if (WIFEXITED(status))
-    ::exit(WEXITSTATUS(status));
-  else if (WIFSIGNALED(status)) {
-    // Try to uplicate the signal of the model-checked process.
-    // This is a temporary hack so we don't try too hard.
-    kill(mc_model_checker->process().pid(), WTERMSIG(status));
-    abort();
-  } else {
-    xbt_die("Unexpected status from model-checked process");
-  }
-}
-
-void s_mc_server::resume(simgrid::mc::Process& process)
-{
-  int res = process.send_message(MC_MESSAGE_CONTINUE);
-  if (res)
-    throw std::system_error(res, std::system_category());
-  process.cache_flags = (mc_process_cache_flags_t) 0;
-}
-
-static
-void throw_socket_error(int fd)
-{
-  int error = 0;
-  socklen_t errlen = sizeof(error);
-  if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&error, &errlen) == -1)
-    error = errno;
-  throw std::system_error(error, std::system_category());
-}
-
-bool s_mc_server::handle_message(char* buffer, ssize_t size)
-{
-  s_mc_message_t base_message;
-  if (size < (ssize_t) sizeof(base_message))
-    xbt_die("Broken message");
-  memcpy(&base_message, buffer, sizeof(base_message));
-
-  switch(base_message.type) {
-
-  case MC_MESSAGE_IGNORE_HEAP:
-    {
-      s_mc_ignore_heap_message_t message;
-      if (size != sizeof(message))
-        xbt_die("Broken messsage");
-      memcpy(&message, buffer, sizeof(message));
-      mc_heap_ignore_region_t region = xbt_new(s_mc_heap_ignore_region_t, 1);
-      *region = message.region;
-      MC_heap_region_ignore_insert(region);
-      break;
-    }
-
-  case MC_MESSAGE_UNIGNORE_HEAP:
-    {
-      s_mc_ignore_memory_message_t message;
-      if (size != sizeof(message))
-        xbt_die("Broken messsage");
-      memcpy(&message, buffer, sizeof(message));
-      MC_heap_region_ignore_remove(
-        (void *)(std::uintptr_t) message.addr, message.size);
-      break;
-    }
-
-  case MC_MESSAGE_IGNORE_MEMORY:
-    {
-      s_mc_ignore_memory_message_t message;
-      if (size != sizeof(message))
-        xbt_die("Broken messsage");
-      memcpy(&message, buffer, sizeof(message));
-      mc_model_checker->process().ignore_region(
-        message.addr, message.size);
-      break;
-    }
-
-  case MC_MESSAGE_STACK_REGION:
-    {
-      s_mc_stack_region_message_t message;
-      if (size != sizeof(message))
-        xbt_die("Broken messsage");
-      memcpy(&message, buffer, sizeof(message));
-      stack_region_t stack_region = xbt_new(s_stack_region_t, 1);
-      *stack_region = message.stack_region;
-      MC_stack_area_add(stack_region);
-    }
-    break;
-
-  case MC_MESSAGE_REGISTER_SYMBOL:
-    {
-      s_mc_register_symbol_message_t message;
-      if (size != sizeof(message))
-        xbt_die("Broken message");
-      memcpy(&message, buffer, sizeof(message));
-      if (message.callback)
-        xbt_die("Support for client-side function proposition is not implemented.");
-      XBT_DEBUG("Received symbol: %s", message.name);
-
-      if (_mc_property_automaton == NULL)
-        _mc_property_automaton = xbt_automaton_new();
-
-      simgrid::mc::Process* process = &mc_model_checker->process();
-      simgrid::mc::remote_ptr<int> address
-        = simgrid::mc::remote((int*) message.data);
-      simgrid::xbt::add_proposition(_mc_property_automaton,
-        message.name,
-        [process, address]() { return process->read(address); }
-        );
-
-      break;
-    }
-
-  case MC_MESSAGE_WAITING:
-    return false;
-
-  case MC_MESSAGE_ASSERTION_FAILED:
-    MC_report_assertion_error();
-    ::exit(SIMGRID_EXIT_SAFETY);
-    break;
-
-  default:
-    xbt_die("Unexpected message from model-checked application");
-
-  }
-  return true;
-}
-
-bool s_mc_server::handle_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:
-      throw std::system_error(errno, std::system_category());
-    }
-  }
-
-  if (socket_pollfd->revents) {
-    if (socket_pollfd->revents & POLLIN) {
-      ssize_t size = MC_receive_message(socket_pollfd->fd, buffer, sizeof(buffer), MSG_DONTWAIT);
-      if (size == -1 && errno != EAGAIN)
-        throw std::system_error(errno, std::system_category());
-      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?");
-  }
-
-  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?");
-  }
-
-  return true;
-}
-
-void s_mc_server::loop()
-{
-  while (mc_model_checker->process().running())
-    this->handle_events();
-}
-
-void s_mc_server::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 std::system_error(errno, std::system_category());
-    } else if (size != sizeof(info))
-        return throw std::runtime_error(
-          "Bad communication with model-checked application");
-    else
-      break;
-  }
-  this->on_signal(&info);
-}
-
-void s_mc_server::handle_waitpid()
-{
-  XBT_DEBUG("Check for wait event");
-  int status;
-  pid_t pid;
-  while ((pid = waitpid(-1, &status, WNOHANG)) != 0) {
-    if (pid == -1) {
-      if (errno == ECHILD) {
-        // No more children:
-        if (mc_model_checker->process().running())
-          xbt_die("Inconsistent state");
-        else
-          break;
-      } else {
-        XBT_ERROR("Could not wait for pid");
-        throw std::system_error(errno, std::system_category());
-      }
-    }
-
-    if (pid == mc_model_checker->process().pid()) {
-
-      // From PTRACE_O_TRACEEXIT:
-      if (status>>8 == (SIGTRAP | (PTRACE_EVENT_EXIT<<8))) {
-        if (ptrace(PTRACE_GETEVENTMSG, pid, 0, &status) == -1)
-          xbt_die("Could not get exit status");
-        if (WIFSIGNALED(status)) {
-          MC_report_crash(status);
-          ::exit(SIMGRID_PROGRAM_CRASH);
-        }
-      }
-
-      // We don't care about signals, just reinject them:
-      if (WIFSTOPPED(status)) {
-        XBT_DEBUG("Stopped with signal %i", (int) WSTOPSIG(status));
-        if (ptrace(PTRACE_CONT, pid, 0, WSTOPSIG(status)) == -1)
-          xbt_die("Could not PTRACE_CONT");
-      }
-
-      else if (WIFEXITED(status) || WIFSIGNALED(status)) {
-        XBT_DEBUG("Child process is over");
-        mc_model_checker->process().terminate(status);
-      }
-    }
-  }
-}
-
-void s_mc_server::on_signal(const struct signalfd_siginfo* info)
-{
-  switch(info->ssi_signo) {
-  case SIGCHLD:
-    this->handle_waitpid();
-    break;
-  default:
-    break;
-  }
-}
-
-void s_mc_server::wait_client(simgrid::mc::Process& process)
-{
-  this->resume(process);
-  while (mc_model_checker->process().running()) {
-    if (!mc_server->handle_events())
-      return;
-  }
-}
-
-void s_mc_server::simcall_handle(simgrid::mc::Process& process, unsigned long pid, int value)
-{
-  s_mc_simcall_handle_message m;
-  memset(&m, 0, sizeof(m));
-  m.type  = MC_MESSAGE_SIMCALL_HANDLE;
-  m.pid   = pid;
-  m.value = value;
-  process.send_message(m);
-  process.cache_flags = (mc_process_cache_flags_t) 0;
-  while (process.running()) {
-    if (!mc_server->handle_events())
-      return;
-  }
-}
-
-}