From 1a106110e5e7f214ea60e7787d02c5565e7193f0 Mon Sep 17 00:00:00 2001 From: Jennifer Richards Date: Wed, 18 Apr 2018 13:34:26 -0400 Subject: [PATCH] Track TID processes and add TID req counts for success/error/pending * 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 | 1 + include/tid_internal.h | 4 ++++ include/tr_tid.h | 5 +--- mon/mon_common.c | 4 ++++ mon/mons.c | 2 +- tid/tids.c | 65 +++++++++++++++++++++++++++++++++++++++++++------- tr/tr_tid_mons.c | 29 ++++++++++++++++++++-- 7 files changed, 95 insertions(+), 15 deletions(-) diff --git a/include/mon_internal.h b/include/mon_internal.h index 8e439d2..4dac054 100644 --- a/include/mon_internal.h +++ b/include/mon_internal.h @@ -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 diff --git a/include/tid_internal.h b/include/tid_internal.h index 658b2e4..b3aa908 100644 --- a/include/tid_internal.h +++ b/include/tid_internal.h @@ -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 diff --git a/include/tr_tid.h b/include/tr_tid.h index 2e839e2..3b06e4b 100644 --- a/include/tr_tid.h +++ b/include/tr_tid.h @@ -42,10 +42,7 @@ #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 */ diff --git a/mon/mon_common.c b/mon/mon_common.c index 440a277..5197958 100644 --- a/mon/mon_common.c +++ b/mon/mon_common.c @@ -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); diff --git a/mon/mons.c b/mon/mons.c index 4d638d6..82495ee 100644 --- a/mon/mons.c +++ b/mon/mons.c @@ -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; } diff --git a/tid/tids.c b/tid/tids.c index 7975ddc..bcbd820 100644 --- a/tid/tids.c +++ b/tid/tids.c @@ -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, diff --git a/tr/tr_tid_mons.c b/tr/tr_tid_mons.c index 38fbbdd..0a18d2d 100644 --- a/tr/tr_tid_mons.c +++ b/tr/tr_tid_mons.c @@ -40,14 +40,39 @@ #include #include +/** + * 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); } -- 2.1.4