Track TID processes and add TID req counts for success/error/pending
authorJennifer Richards <jennifer@painless-security.com>
Wed, 18 Apr 2018 17:34:26 +0000 (13:34 -0400)
committerJennifer Richards <jennifer@painless-security.com>
Wed, 18 Apr 2018 17:34:26 +0000 (13:34 -0400)
  * Track TID processes by pid
  * Add handlers for the TID req counts

Still only check for terminated TID processes after the next one comes
in, should either periodically sweep or check this after a child
terminates and sends SIGCHLD

include/mon_internal.h
include/tid_internal.h
include/tr_tid.h
mon/mon_common.c
mon/mons.c
tid/tids.c
tr/tr_tid_mons.c

index 8e439d2..4dac054 100644 (file)
@@ -100,6 +100,7 @@ enum mon_opt_type {
   // System statistics
   OPT_TYPE_SHOW_UPTIME,
   OPT_TYPE_SHOW_TID_REQ_COUNT,
+  OPT_TYPE_SHOW_TID_REQ_ERR_COUNT,
   OPT_TYPE_SHOW_TID_REQ_PENDING,
 
   // Dynamic trust router state
index 658b2e4..b3aa908 100644 (file)
@@ -88,6 +88,7 @@ struct tidc_instance {
 
 struct tids_instance {
   int req_count;
+  int error_count;
   char *priv_key;
   char *ipaddr;
   const char *hostname;
@@ -96,6 +97,7 @@ struct tids_instance {
   void *cookie;
   unsigned int tids_port;
   TR_NAME *gss_name;           /* GSS name client used for authentication */
+  GArray *pids; /* PIDs of active tids processes */
 };
 
 /** Decrement a reference to #json when this tid_req is cleaned up. A
@@ -116,4 +118,6 @@ TID_RC tid_resp_cpy(TID_RESP *dst, TID_RESP *src);
 void tid_resp_set_cons(TID_RESP *resp, TR_CONSTRAINT_SET *cons);
 void tid_resp_set_error_path(TID_RESP *resp, json_t *ep);
 
+void tids_sweep_procs(TIDS_INSTANCE *tids);
+
 #endif
index 2e839e2..3b06e4b 100644 (file)
 
 #define TR_TID_MAX_AAA_SERVERS 10
 
-int tr_tids_event_init(struct event_base *base,
-                       TIDS_INSTANCE *tids,
-                       TR_CFG_MGR *cfg_mgr,
-                       TRPS_INSTANCE *trps,
+int tr_tids_event_init(struct event_base *base, TIDS_INSTANCE *tids, TR_CFG_MGR *cfg_mgr, TRPS_INSTANCE *trps,
                        struct tr_socket_event *tids_ev);
 
 /* tr_tid_mons.c */
index 440a277..5197958 100644 (file)
@@ -96,6 +96,9 @@ const char *mon_opt_type_to_string(MON_OPT_TYPE opt_type)
     case OPT_TYPE_SHOW_TID_REQ_COUNT:
       return "tid_req_count";
 
+    case OPT_TYPE_SHOW_TID_REQ_ERR_COUNT:
+      return "tid_req_error_count";
+
     case OPT_TYPE_SHOW_TID_REQ_PENDING:
       return "tid_req_pending";
 
@@ -121,6 +124,7 @@ MON_OPT_TYPE mon_opt_type_from_string(const char *s)
   return_if_matches(s, OPT_TYPE_SHOW_SERIAL);
   return_if_matches(s, OPT_TYPE_SHOW_UPTIME);
   return_if_matches(s, OPT_TYPE_SHOW_TID_REQ_COUNT);
+  return_if_matches(s, OPT_TYPE_SHOW_TID_REQ_ERR_COUNT);
   return_if_matches(s, OPT_TYPE_SHOW_TID_REQ_PENDING);
   return_if_matches(s, OPT_TYPE_SHOW_ROUTES);
   return_if_matches(s, OPT_TYPE_SHOW_COMMUNITIES);
index 4d638d6..82495ee 100644 (file)
@@ -238,7 +238,7 @@ int mons_accept(MONS_INSTANCE *mons, int listen)
   }
 
   /* clean up any processes that have completed */
-  while (waitpid(-1, 0, WNOHANG) > 0);
+  //while (waitpid(-1, 0, WNOHANG) > 0); TODO: only clean up our own pids
 
   return 0;
 }
index 7975ddc..bcbd820 100644 (file)
@@ -310,9 +310,26 @@ cleanup:
   return resp_msg;
 }
 
+static int tids_destructor(void *object)
+{
+  TIDS_INSTANCE *tids = talloc_get_type_abort(object, TIDS_INSTANCE);
+  if (tids->pids)
+    g_array_unref(tids->pids);
+  return 0;
+}
+
 TIDS_INSTANCE *tids_new(TALLOC_CTX *mem_ctx)
 {
-  return talloc_zero(mem_ctx, TIDS_INSTANCE);
+  TIDS_INSTANCE *tids = talloc_zero(mem_ctx, TIDS_INSTANCE);
+  if (tids) {
+    tids->pids = g_array_new(FALSE, FALSE, sizeof(pid_t));
+    if (tids->pids == NULL) {
+      talloc_free(tids);
+      return NULL;
+    }
+    talloc_set_destructor((void *)tids, tids_destructor);
+  }
+  return tids;
 }
 
 /**
@@ -323,8 +340,9 @@ TIDS_INSTANCE *tids_new(TALLOC_CTX *mem_ctx)
  */
 TIDS_INSTANCE *tids_create(void)
 {
-  return talloc_zero(NULL, TIDS_INSTANCE);
+  return tids_new(NULL);
 }
+
 /* Get a listener for tids requests, returns its socket fd. Accept
  * connections with tids_accept() */
 nfds_t tids_get_listener(TIDS_INSTANCE *tids,
@@ -389,8 +407,6 @@ int tids_accept(TIDS_INSTANCE *tids, int listen)
     return 1;
   }
 
-  tids->req_count++; /* increment this in both processes after forking */
-
   if (pid == 0) {
     close(listen);
     tr_gss_handle_connection(conn,
@@ -400,16 +416,49 @@ int tids_accept(TIDS_INSTANCE *tids, int listen)
     );
     close(conn);
     exit(0); /* exit to kill forked child process */
-  } else {
-    close(conn);
   }
 
-  /* clean up any processes that have completed  (TBD: move to main loop?) */
-  while (waitpid(-1, 0, WNOHANG) > 0);
+  /* Only the parent process gets here */
+  close(conn); /* connection belongs to the child */
+  g_array_append_val(tids->pids, pid); /* remember the PID of our child process */
+
+  /* clean up any processes that have completed */
+  tids_sweep_procs(tids);
 
   return 0;
 }
 
+void tids_sweep_procs(TIDS_INSTANCE *tids)
+{
+  guint ii;
+  pid_t pid;
+  int status;
+
+  /* loop backwards over the array so we can remove elements as we go */
+  for (ii=tids->pids->len; ii > 0; ii--) {
+    /* ii-1 is the current index */
+    pid = g_array_index(tids->pids, pid_t, ii-1);
+    if (waitpid(pid, &status, WNOHANG) > 0) {
+      /* the process exited */
+      tr_debug("tids_sweep_procs: TID process %d terminated.", pid);
+
+      g_array_remove_index_fast(tids->pids, ii-1); /* disturbs only indices >= ii-1 which we've already handled */
+      if (WIFEXITED(status) && (WEXITSTATUS(status) == 0)) {
+        tr_debug("tids_sweep_procs: TID process succeeded");
+        tids->req_count++;
+      } else {
+        tids->error_count++;
+
+        if (WIFEXITED(status)) {
+          tr_debug("tids_sweep_procs: TID process %d exited with status %d", pid, WTERMSIG(status));
+        } else if (WIFSIGNALED(status)) {
+          tr_debug("tids_sweep_procs: TID process %d terminated by signal %d", pid, WTERMSIG(status));
+        }
+      }
+    }
+  }
+}
+
 /* Process tids requests forever. Should not return except on error. */
 int tids_start (TIDS_INSTANCE *tids,
                 TIDS_REQ_FUNC *req_handler,
index 38fbbdd..0a18d2d 100644 (file)
 #include <mon_internal.h>
 #include <mons_handlers.h>
 
+/**
+ * Get the count of completed TID requests
+ */
 static MON_RC handle_show_req_count(void *cookie, json_t **response_ptr)
 {
   TIDS_INSTANCE *tids = talloc_get_type_abort(cookie, TIDS_INSTANCE);
   *response_ptr = json_integer(tids->req_count);
-  return (*response_ptr) ? MON_NOMEM : MON_SUCCESS;
+  return (*response_ptr == NULL) ? MON_NOMEM : MON_SUCCESS;
+}
+
+static MON_RC handle_show_req_err_count(void *cookie, json_t **response_ptr)
+{
+  TIDS_INSTANCE *tids = talloc_get_type_abort(cookie, TIDS_INSTANCE);
+  *response_ptr = json_integer(tids->error_count);
+  return (*response_ptr == NULL) ? MON_NOMEM : MON_SUCCESS;
+}
+
+static MON_RC handle_show_req_pending(void *cookie, json_t **response_ptr)
+{
+  TIDS_INSTANCE *tids = talloc_get_type_abort(cookie, TIDS_INSTANCE);
+  *response_ptr = json_integer(tids->pids->len);
+  return (*response_ptr == NULL) ? MON_NOMEM : MON_SUCCESS;
 }
 
 void tr_tid_register_mons_handlers(TIDS_INSTANCE *tids, MONS_INSTANCE *mons)
 {
-  mons_register_handler(mons, MON_CMD_SHOW, OPT_TYPE_SHOW_TID_REQ_COUNT, handle_show_req_count, tids);
+  mons_register_handler(mons,
+                        MON_CMD_SHOW, OPT_TYPE_SHOW_TID_REQ_COUNT,
+                        handle_show_req_count, tids);
+  mons_register_handler(mons,
+                        MON_CMD_SHOW, OPT_TYPE_SHOW_TID_REQ_ERR_COUNT,
+                        handle_show_req_err_count, tids);
+  mons_register_handler(mons,
+                        MON_CMD_SHOW, OPT_TYPE_SHOW_TID_REQ_PENDING,
+                        handle_show_req_pending, tids);
 }