gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r28496 - msh/src


From: gnunet
Subject: [GNUnet-SVN] r28496 - msh/src
Date: Sun, 11 Aug 2013 14:58:14 +0200

Author: harsha
Date: 2013-08-11 14:58:14 +0200 (Sun, 11 Aug 2013)
New Revision: 28496

Added:
   msh/src/mshd_pmonitor.c
   msh/src/mshd_pmonitor.h
Modified:
   msh/src/Makefile.am
   msh/src/mshd.c
Log:
- process monitoring


Modified: msh/src/Makefile.am
===================================================================
--- msh/src/Makefile.am 2013-08-11 12:57:53 UTC (rev 28495)
+++ msh/src/Makefile.am 2013-08-11 12:58:14 UTC (rev 28496)
@@ -4,7 +4,7 @@
 
 mshd_SOURCES = mshd.c mshd.h util.c util.h mtypes.h \
   common.h bitmap.c bitmap.h addressmap.c addressmap.h reduce.h reduce.c \
-  mshd-server.c
+  mshd-server.c mshd_pmonitor.c mshd_pmonitor.h
 mshd_LDADD = -lgnunetutil -lm
 
 msh_SOURCES = msh.c mtypes.h

Modified: msh/src/mshd.c
===================================================================
--- msh/src/mshd.c      2013-08-11 12:57:53 UTC (rev 28495)
+++ msh/src/mshd.c      2013-08-11 12:58:14 UTC (rev 28496)
@@ -429,7 +429,7 @@
   listen_mode = LISTEN_MODE_SERV;
   rmap = addressmap_create_reverse_mapping (addrmap);
   pid = (intmax_t) getpid ();
-  dtemp - GNUNET_DISK_mkdtemp ("mshd");
+  dtemp = GNUNET_DISK_mkdtemp ("mshd");
   GNUNET_assert (NULL != dtemp);
   GNUNET_assert (0 < asprintf (&unixpath, "%s/%j.sock", dtemp, pid));
   GNUNET_free (dtemp);

Added: msh/src/mshd_pmonitor.c
===================================================================
--- msh/src/mshd_pmonitor.c                             (rev 0)
+++ msh/src/mshd_pmonitor.c     2013-08-11 12:58:14 UTC (rev 28496)
@@ -0,0 +1,281 @@
+/**
+ * @file mshd_pmonitor.c
+ * @brief process monitoring functions
+ * @author Sree Harsha Totakura <address@hidden> 
+ */
+
+#include "common.h"
+#include "gnunet/gnunet_util_lib.h"
+#include "mshd_pmonitor.h"
+
+/**
+ * Generic logging shortcut
+ */
+#define LOG(kind, ...)                                   \
+  GNUNET_log_from (kind, "mshd-pmonitor", __VA_ARGS__)
+
+/**
+ * Debug logging shorthand
+ */
+#define LOG_DEBUG(...)                          \
+  LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
+
+
+struct MonitorCtx
+{
+  /**
+   * The process to monitor
+   */
+  struct GNUNET_OS_Process *proc;
+
+  /**
+   * Termination notification callback
+   */
+  MSH_ProcExitCallback cb;
+  
+  /**
+   * closure for the above callback
+   */
+  void *cls;
+};
+
+/**
+ * Task to kill the child
+ */
+static GNUNET_SCHEDULER_TaskIdentifier child_death_task_id;
+
+/**
+ * Pipe used to communicate shutdown via signal.
+ */
+static struct GNUNET_DISK_PipeHandle *sigpipe;
+
+/**
+ * Signal context for SIGCHLD
+ */
+static struct GNUNET_SIGNAL_Context *shc_chld;
+
+/**
+ * hashmap for storing process monitoring context
+ */
+static struct GNUNET_CONTAINER_MultiHashMap32 *map;
+
+
+/**
+ * Task triggered whenever we receive a SIGCHLD (child
+ * process died).
+ *
+ * @param cls closure, NULL if we need to self-restart
+ * @param tc context
+ */
+static void
+child_death_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  const struct GNUNET_DISK_FileHandle *pr;
+  struct MonitorCtx *ctx;
+  MSH_ProcExitCallback cb;
+  void *cb_cls;
+  char c[16];
+  enum GNUNET_OS_ProcessStatusType type;
+  int status;
+  pid_t cid;
+  int code;
+
+  cb = NULL;
+  pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ);
+  child_death_task_id = GNUNET_SCHEDULER_NO_TASK;
+  if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY))
+  {
+    child_death_task_id =
+       GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
+                                       pr, &child_death_task, NULL);
+    return;
+  }
+  /* consume the signal */
+  GNUNET_break (0 < GNUNET_DISK_file_read (pr, &c, sizeof (c)));
+  LOG_DEBUG ("Got SIGCHLD\n");
+  cid = waitpid (-1, &status, WNOHANG);
+  if (0 == cid)
+  {
+    LOG_DEBUG ("Child hasn't died.  Resuming to monitor its status\n");
+    goto resume;
+  }
+  if (-1 == cid)
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "wait");
+    goto resume;
+  }
+  type = GNUNET_OS_PROCESS_UNKNOWN;
+  if (WIFEXITED (status))
+  {
+    type = GNUNET_OS_PROCESS_EXITED;
+    code = WEXITSTATUS (status);
+  }
+  if (WIFSIGNALED (status))
+  {
+    type = GNUNET_OS_PROCESS_SIGNALED;
+    code = WTERMSIG (status);
+  }
+  if (GNUNET_OS_PROCESS_UNKNOWN == type)
+  {
+    GNUNET_break (0);
+    goto resume;
+  }
+  ctx = GNUNET_CONTAINER_multihashmap32_get (map, (uint32_t) cid);
+  if (NULL == ctx)
+    goto resume;
+  cb = ctx->cb;
+  cb_cls = ctx->cls;
+  GNUNET_free (ctx);
+  
+ resume:
+  child_death_task_id =
+      GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
+                                      pr, &child_death_task, NULL);
+  if (NULL != cb)
+    cb (cb_cls, type, code);
+}
+
+
+/**
+ * Signal handler called for SIGCHLD.
+ */
+static void
+sighandler_child_death ()
+{
+  static char c;
+  int old_errno;       /* back-up errno */
+
+  old_errno = errno;
+  GNUNET_break (1 ==
+                GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle
+                                        (sigpipe, GNUNET_DISK_PIPE_END_WRITE),
+                                        &c, sizeof (c)));
+  errno = old_errno;
+}
+
+
+/**
+ * Initialise process monitoring subsystem.  Registers SIGCHLD signal handler
+ * and the necessary pipe mechanism for reading the signal notification in a
+ * safe way
+ */
+void
+MSH_pmonitor_init ()
+{
+  const struct GNUNET_DISK_FileHandle *pr;
+
+  GNUNET_assert (NULL == sigpipe);
+  GNUNET_assert (NULL == shc_chld);
+  GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == child_death_task_id);
+  GNUNET_assert (NULL != (sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, 
+                                                      GNUNET_NO, GNUNET_NO)));
+  GNUNET_assert (NULL != (shc_chld = GNUNET_SIGNAL_handler_install 
+                          (GNUNET_SIGCHLD, &sighandler_child_death)));
+  pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ);
+  child_death_task_id =
+      GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
+                                      pr, &child_death_task, NULL);
+  
+}
+
+
+/**
+ * Iterator over hash map entries.
+ *
+ * @param cls closure
+ * @param key current key code
+ * @param value value in the hash map
+ * @return GNUNET_YES if we should continue to
+ *         iterate,
+ *         GNUNET_NO if not.
+ */
+static int
+cleanup_iterator (void *cls, uint32_t key, void *value)
+{
+  struct MonitorCtx *ctx = value;
+  pid_t pid;
+
+  pid = GNUNET_OS_process_get_pid (ctx->proc);
+  GNUNET_assert (GNUNET_YES == 
+                 GNUNET_CONTAINER_multihashmap32_remove (map,
+                                                         (uint32_t) pid,
+                                                         ctx));
+  GNUNET_free (ctx);
+}
+
+
+/**
+ * shutdown process monitoring subsystem
+ */
+void
+MSH_pmonitor_shutdown ()
+{
+  /* fixme clear monitoring contexts */
+  GNUNET_break (GNUNET_SYSERR != 
+                GNUNET_CONTAINER_multihashmap32_iterate (map,
+                                                         &cleanup_iterator,
+                                                         NULL));
+  GNUNET_assert (NULL != sigpipe);
+  GNUNET_assert (NULL != shc_chld);
+  if (GNUNET_SCHEDULER_NO_TASK != child_death_task_id)
+  {
+    GNUNET_SCHEDULER_cancel (child_death_task_id);
+    child_death_task_id = GNUNET_SCHEDULER_NO_TASK;
+  }
+  GNUNET_SIGNAL_handler_uninstall (shc_chld);
+  shc_chld = NULL;
+  GNUNET_DISK_pipe_close (sigpipe);
+  sigpipe = NULL;
+}
+
+
+/**
+ * Monitors a process for its termination.
+ *
+ * @param proc the process to monitor for termination
+ * @param cb the callback to be called for notifying the termination of the
+ *    process
+ * @param cls the closure for the above callback
+ */
+void
+MSH_monitor_process (struct GNUNET_OS_Process *proc,
+                     MSH_ProcExitCallback cb, void *cls)
+{
+  struct MonitorCtx *ctx;
+  pid_t pid;
+
+  GNUNET_assert (NULL != map);
+  pid = GNUNET_OS_process_get_pid (proc);
+  ctx->proc = proc;
+  ctx->cb = cb;
+  ctx->cls = cls;
+  GNUNET_assert 
+      (GNUNET_OK ==
+       GNUNET_CONTAINER_multihashmap32_put (map, (uint32_t) pid, ctx,
+                                            
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+}
+
+
+/**
+ * Stop monitoring a process
+ *
+ * @param proc
+ * @return GNUNET_OK upon success; GNUNET_SYSERR if the process is not being
+ *   monitored earlier
+ */
+int
+MSH_monitor_process_cancel (struct GNUNET_OS_Process *proc)
+{
+  struct MonitorCtx *ctx;
+  pid_t pid;
+  
+  GNUNET_assert (NULL != map);
+  pid = GNUNET_OS_process_get_pid (proc);
+  ctx = GNUNET_CONTAINER_multihashmap32_get (map, (uint32_t) pid);
+  if (NULL == ctx)
+    return GNUNET_SYSERR;
+  GNUNET_assert (GNUNET_YES == 
+                 GNUNET_CONTAINER_multihashmap32_remove 
+                 (map, (uint32_t) pid, ctx));
+  GNUNET_free (ctx);
+}

Added: msh/src/mshd_pmonitor.h
===================================================================
--- msh/src/mshd_pmonitor.h                             (rev 0)
+++ msh/src/mshd_pmonitor.h     2013-08-11 12:58:14 UTC (rev 28496)
@@ -0,0 +1,48 @@
+/**
+ * @file mshd_pmonitor.h
+ * @brief interface for process monitoring functions
+ * @author Sree Harsha Totakura <address@hidden> 
+ */
+
+#include <gnunet/gnunet_os_lib.h>
+
+/**
+ * Initialise process monitoring subsystem.  Registers SIGCHLD signal handler
+ * and the necessary pipe mechanism for reading the signal notification in a
+ * safe way
+ */
+void
+MSH_pmonitor_init ();
+
+
+/**
+ * shutdown process monitoring subsystem
+ */
+void
+MSH_pmonitor_shutdown ();
+
+
+/**
+ * Callbacks of this type can be supplied to MSH_monitor_process() to be
+ * notified when the corresponding processes exits.
+ *
+ * @param cls the closure passed to MSH_monitor_process()
+ * @param type the process status type
+ * @param long the return/exit code of the process
+ */
+typedef void (*MSH_ProcExitCallback) (void *cls,
+                                      enum GNUNET_OS_ProcessStatusType type,
+                                      int code);
+
+
+/**
+ * Monitors a process for its termination.
+ *
+ * @param proc the process to monitor for termination
+ * @param cb the callback to be called for notifying the termination of the
+ *    process
+ * @param cls the closure for the above callback
+ */
+void
+MSH_monitor_process (struct GNUNET_OS_Process *proc,
+                     MSH_ProcExitCallback cb, void *cls);




reply via email to

[Prev in Thread] Current Thread [Next in Thread]