Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Allow to mark actors as daemon
authorMartin Quinson <martin.quinson@loria.fr>
Fri, 10 Mar 2017 22:09:29 +0000 (23:09 +0100)
committerMartin Quinson <martin.quinson@loria.fr>
Fri, 10 Mar 2017 22:11:20 +0000 (23:11 +0100)
Daemon actors are automatically killed when the last non-daemon
terminates

ChangeLog
examples/msg/CMakeLists.txt
examples/msg/process-daemon/process-daemon.c [new file with mode: 0644]
examples/msg/process-daemon/process-daemon.tesh [new file with mode: 0644]
include/simgrid/msg.h
src/msg/msg_process.cpp
src/simix/ActorImpl.cpp
src/simix/ActorImpl.hpp
src/simix/smx_global.cpp
src/simix/smx_private.h

index 3432860..77ee0e4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -10,7 +10,9 @@ SimGrid (3.15) UNRELEASED; urgency=low
    That's a point in the routing algorithm, let's avoid wrong simplifications.
 
  MSG
- - New function: MSG_process_yield()
+ - New: MSG_process_yield()
+ - New: MSG_process_daemon(). Daemon processes are automatically killed 
+   when the last non-daemon process terminates
  - Renamed MSG_energy_plugin_init() -> MSG_host_energy_plugin_init()
    to make room for the upcoming network energy plugin.
 
index a427f2d..f25ab08 100644 (file)
@@ -2,7 +2,7 @@
 foreach(x actions-comm actions-storage app-masterworker app-pingpong app-pmm app-token-ring async-yield async-wait async-waitall 
           async-waitany cloud-capping cloud-masterworker cloud-migration cloud-simple cloud-two-tasks
           dht-chord dht-pastry energy-consumption energy-onoff energy-pstate energy-ptask energy-vm platform-failures 
-          io-file io-remote io-storage task-priority process-create process-kill process-migration process-suspend 
+          io-file io-remote io-storage task-priority process-create process-daemon process-kill process-migration process-suspend 
           platform-properties process-startkilltime synchro-semaphore trace-categories 
           trace-route-user-variables trace-link-user-variables trace-masterworker trace-platform 
           trace-process-migration trace-host-user-variables)
@@ -96,7 +96,7 @@ set(xml_files    ${xml_files}     ${CMAKE_CURRENT_SOURCE_DIR}/actions-comm/actio
 foreach(x actions-comm actions-storage app-bittorrent app-chainsend app-masterworker app-pingpong app-token-ring
           async-yield async-wait async-waitall async-waitany cloud-capping cloud-masterworker cloud-migration cloud-simple 
           cloud-two-tasks dht-chord dht-pastry dht-kademlia platform-failures io-file io-remote io-storage task-priority 
-          process-create process-kill process-migration process-suspend platform-properties synchro-semaphore 
+          process-create process-daemon process-kill process-migration process-suspend platform-properties synchro-semaphore 
           process-startkilltime)
   ADD_TESH_FACTORIES(msg-${x} "thread;ucontext;raw;boost" --setenv bindir=${CMAKE_BINARY_DIR}/examples/msg/${x} --setenv srcdir=${CMAKE_HOME_DIRECTORY}/examples/platforms --cd ${CMAKE_HOME_DIRECTORY}/examples/msg/${x} ${x}.tesh)
 endforeach()
diff --git a/examples/msg/process-daemon/process-daemon.c b/examples/msg/process-daemon/process-daemon.c
new file mode 100644 (file)
index 0000000..2806042
--- /dev/null
@@ -0,0 +1,49 @@
+/* Copyright (c) 2017. 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 "simgrid/msg.h"
+
+XBT_LOG_NEW_DEFAULT_CATEGORY(msg_process_daemon, "Messages specific for this msg example");
+
+/* The worker process, working for a while before leaving */
+static int worker(int argc, char* argv[])
+{
+  XBT_INFO("Let's do some work (for 10 sec on Boivin).");
+  msg_task_t task = MSG_task_create("easy work", 980.95e6, 0, NULL);
+  MSG_task_execute(task);
+  MSG_task_destroy(task);
+
+  XBT_INFO("I'm done now. I leave even if it makes the daemon die.");
+  return 0;
+}
+
+/* The daemon, displaying a message every 3 seconds until all other processes stop */
+static int daemon(int argc, char* argv[])
+{
+  MSG_process_daemonize(MSG_process_self());
+
+  while (1) {
+    XBT_INFO("Hello from the infinite loop");
+    MSG_process_sleep(3.0);
+  }
+
+  XBT_INFO("I will never reach that point: daemons are killed when regular processes are done");
+  return 0;
+}
+
+int main(int argc, char* argv[])
+{
+  MSG_init(&argc, argv);
+  xbt_assert(argc > 1, "Usage: %s platform_file\n\tExample: %s msg_platform.xml\n", argv[0], argv[0]);
+
+  MSG_create_environment(argv[1]);
+  xbt_dynar_t hosts = MSG_hosts_as_dynar();
+  MSG_process_create("worker", worker, NULL, xbt_dynar_getfirst_as(hosts, msg_host_t));
+  MSG_process_create("daemon", daemon, NULL, xbt_dynar_getlast_as(hosts, msg_host_t));
+  xbt_dynar_free(&hosts);
+  msg_error_t res = MSG_main();
+
+  return res != MSG_OK;
+}
diff --git a/examples/msg/process-daemon/process-daemon.tesh b/examples/msg/process-daemon/process-daemon.tesh
new file mode 100644 (file)
index 0000000..25c0f10
--- /dev/null
@@ -0,0 +1,11 @@
+#! ./tesh
+
+p Testing the process daemonization feature of MSG
+
+$ $SG_TEST_EXENV ${bindir:=.}/process-daemon ${srcdir:=.}/small_platform.xml "--log=root.fmt:[%10.6r]%e(%i:%P@%h)%e%m%n"
+> [  0.000000] (1:worker@Boivin) Let's do some work (for 10 sec on Boivin).
+> [  0.000000] (2:daemon@Tremblay) Hello from the infinite loop
+> [  3.000000] (2:daemon@Tremblay) Hello from the infinite loop
+> [  6.000000] (2:daemon@Tremblay) Hello from the infinite loop
+> [  9.000000] (2:daemon@Tremblay) Hello from the infinite loop
+> [ 10.000000] (1:worker@Boivin) I'm done now. I leave even if it makes the daemon die.
index c65b456..c553e6e 100644 (file)
@@ -316,6 +316,7 @@ XBT_PUBLIC(int) MSG_process_is_suspended(msg_process_t process);
 XBT_PUBLIC(void) MSG_process_on_exit(int_f_pvoid_pvoid_t fun, void *data);
 XBT_PUBLIC(void) MSG_process_auto_restart_set(msg_process_t process, int auto_restart);
 
+XBT_PUBLIC(void) MSG_process_daemonize(msg_process_t process);
 XBT_PUBLIC(msg_process_t) MSG_process_restart(msg_process_t process);
 
 /************************** Task handling ************************************/
index 72f9207..cf9b59d 100644 (file)
@@ -458,7 +458,7 @@ void MSG_process_on_exit(int_f_pvoid_pvoid_t fun, void *data) {
 XBT_PUBLIC(void) MSG_process_auto_restart_set(msg_process_t process, int auto_restart) {
   simcall_process_auto_restart_set(process,auto_restart);
 }
-/*
+/**
  * \ingroup m_process_management
  * \brief Restarts a process from the beginning.
  */
@@ -466,4 +466,14 @@ XBT_PUBLIC(msg_process_t) MSG_process_restart(msg_process_t process) {
   return simcall_process_restart(process);
 }
 
+/** @ingroup m_process_management
+ * @brief This process will be terminated automatically when the last non-daemon process finishes
+ */
+XBT_PUBLIC(void) MSG_process_daemonize(msg_process_t process)
+{
+  simgrid::simix::kernelImmediate([process]() {
+    process->daemonize();
+  });
+}
+
 SG_END_DECL()
index 970ecec..502ffea 100644 (file)
@@ -168,6 +168,35 @@ ActorImpl::~ActorImpl()
   xbt_dict_free(&this->properties);
 }
 
+static int dying_daemon(void* exit_status, void* data)
+{
+  std::vector<ActorImpl*>* vect = &simix_global->daemons;
+
+  auto it = std::find(vect->begin(), vect->end(), static_cast<ActorImpl*>(data));
+  xbt_assert(it != vect->end(), "The dying daemon is not a daemon after all. Please report that bug.");
+
+  /* Don't move the whole content since we don't really care about the order */
+  std::swap(*it, vect->back());
+  vect->pop_back();
+
+  return 0;
+}
+/** This process will be terminated automatically when the last non-daemon process finishes */
+void ActorImpl::daemonize()
+{
+  if (!daemon) {
+    daemon = true;
+    simix_global->daemons.push_back(this);
+    SIMIX_process_on_exit(this, dying_daemon, this);
+  }
+}
+
+/** Whether this process is daemonized */
+bool ActorImpl::isDaemon()
+{
+  return daemon;
+}
+
 void create_maestro(std::function<void()> code)
 {
   smx_actor_t maestro = nullptr;
index c7ce8cd..8bab69b 100644 (file)
@@ -85,7 +85,11 @@ public:
 
   simgrid::s4u::ActorPtr iface() { return s4u::ActorPtr(&piface_); }
 
+  void daemonize();
+  bool isDaemon();
+
 private:
+  bool daemon = false;
   std::atomic_int_fast32_t refcount_ { 1 };
   simgrid::s4u::Actor piface_; // Our interface is part of ourselves
 };
index 1844725..0c2a87f 100644 (file)
@@ -541,7 +541,15 @@ void SIMIX_run()
     /* Clean processes to destroy */
     SIMIX_process_empty_trash();
 
-    XBT_DEBUG("### time %f, empty %d", time, xbt_dynar_is_empty(simix_global->process_to_run));
+    XBT_DEBUG("### time %f, #processes %zu, #to_run %zu", time, simix_global->process_list.size(),
+              xbt_dynar_length(simix_global->process_to_run));
+
+    /* If only daemon processes remain, cancel their actions, mark them to die and reschedule them */
+    if (simix_global->process_list.size() == simix_global->daemons.size())
+      for (const auto& dmon : simix_global->daemons) {
+        XBT_DEBUG("Kill %s", dmon->cname());
+        SIMIX_process_kill(dmon, simix_global->maestro_process);
+      }
 
     if (xbt_dynar_is_empty(simix_global->process_to_run) &&
         !simix_global->process_list.empty())
index f0072b9..6999488 100644 (file)
@@ -49,6 +49,8 @@ public:
 
   std::vector<simgrid::xbt::Task<void()>> tasks;
   std::vector<simgrid::xbt::Task<void()>> tasksTemp;
+
+  std::vector<simgrid::simix::ActorImpl*> daemons;
 };
 
 }