// 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
struct tids_instance {
int req_count;
+ int error_count;
char *priv_key;
char *ipaddr;
const char *hostname;
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
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
#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 */
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";
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);
}
/* 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;
}
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;
}
/**
*/
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,
return 1;
}
- tids->req_count++; /* increment this in both processes after forking */
-
if (pid == 0) {
close(listen);
tr_gss_handle_connection(conn,
);
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,
#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);
}