diff --git a/apps/backend/backend_commit.c b/apps/backend/backend_commit.c index fa11b3b7..bfadecd8 100644 --- a/apps/backend/backend_commit.c +++ b/apps/backend/backend_commit.c @@ -956,13 +956,13 @@ from_client_restart_one(clixon_handle h, /* Application may define extra xml in its reset function*/ if ((resetfn = clixon_plugin_api_get(cp)->ca_reset) != NULL){ wh = NULL; - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; if ((retval = resetfn(h, db)) < 0) { clixon_debug(CLIXON_DBG_DEFAULT, "plugin_start() failed"); goto done; } - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; } /* 1. Start transaction */ diff --git a/apps/backend/backend_plugin.c b/apps/backend/backend_plugin.c index 647a410e..7b18e65d 100644 --- a/apps/backend/backend_plugin.c +++ b/apps/backend/backend_plugin.c @@ -84,17 +84,17 @@ clixon_plugin_reset_one(clixon_plugin_t *cp, if ((fn = clixon_plugin_api_get(cp)->ca_reset) != NULL){ wh = NULL; - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; if (fn(h, db) < 0) { - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; if (clixon_err_category() < 0) clixon_log(h, LOG_WARNING, "%s: Internal error: Reset callback in plugin: %s returned -1 but did not make a clixon_err call", __FUNCTION__, clixon_plugin_name_get(cp)); goto done; } - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; } retval = 0; @@ -145,10 +145,10 @@ clixon_plugin_pre_daemon_one(clixon_plugin_t *cp, if ((fn = clixon_plugin_api_get(cp)->ca_pre_daemon) != NULL){ wh = NULL; - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; if (fn(h) < 0) { - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; if (clixon_err_category() < 0) clixon_log(h, LOG_WARNING, "%s: Internal error: Pre-daemon callback in plugin:\ @@ -156,7 +156,7 @@ clixon_plugin_pre_daemon_one(clixon_plugin_t *cp, __FUNCTION__, clixon_plugin_name_get(cp)); goto done; } - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; } retval = 0; @@ -207,17 +207,17 @@ clixon_plugin_daemon_one(clixon_plugin_t *cp, if ((fn = clixon_plugin_api_get(cp)->ca_daemon) != NULL){ wh = NULL; - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; if (fn(h) < 0) { - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; if (clixon_err_category() < 0) clixon_log(h, LOG_WARNING, "%s: Internal error: Daemon callback in plugin: %s returned -1 but did not make a clixon_err call", __FUNCTION__, clixon_plugin_name_get(cp)); goto done; } - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; } retval = 0; @@ -294,17 +294,17 @@ clixon_plugin_statedata_one(clixon_plugin_t *cp, if ((x = xml_new(DATASTORE_TOP_SYMBOL, NULL, CX_ELMNT)) == NULL) goto done; wh = NULL; - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; if (fn(h, nsc, xpath, x) < 0){ - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; if (clixon_err_category() < 0) clixon_log(h, LOG_WARNING, "%s: Internal error: State callback in plugin: %s returned -1 but did not make a clixon_err call", __FUNCTION__, clixon_plugin_name_get(cp)); goto fail; /* Dont quit here on user callbacks */ } - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; } if (xp && x) @@ -441,11 +441,11 @@ clixon_plugin_lockdb_one(clixon_plugin_t *cp, if ((fn = clixon_plugin_api_get(cp)->ca_lockdb) != NULL){ wh = NULL; - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; if (fn(h, db, lock, id) < 0) goto done; - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; } retval = 0; @@ -623,17 +623,17 @@ plugin_transaction_begin_one(clixon_plugin_t *cp, if ((fn = clixon_plugin_api_get(cp)->ca_trans_begin) != NULL){ wh = NULL; - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; if (fn(h, (transaction_data)td) < 0){ - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; if (!clixon_err_category()) /* sanity: log if clixon_err() is not called ! */ clixon_log(h, LOG_NOTICE, "%s: Plugin '%s' callback does not make clixon_err call on error", __FUNCTION__, clixon_plugin_name_get(cp)); goto done; } - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; } retval = 0; @@ -686,10 +686,10 @@ plugin_transaction_validate_one(clixon_plugin_t *cp, if ((fn = clixon_plugin_api_get(cp)->ca_trans_validate) != NULL){ wh = NULL; - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; if (fn(h, (transaction_data)td) < 0){ - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; if (!clixon_err_category()) /* sanity: log if clixon_err() is not called ! */ clixon_log(h, LOG_NOTICE, "%s: Plugin '%s' callback does not make clixon_err call on error", @@ -697,7 +697,7 @@ plugin_transaction_validate_one(clixon_plugin_t *cp, goto done; } - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; } retval = 0; @@ -748,17 +748,17 @@ plugin_transaction_complete_one(clixon_plugin_t *cp, if ((fn = clixon_plugin_api_get(cp)->ca_trans_complete) != NULL){ wh = NULL; - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; if (fn(h, (transaction_data)td) < 0){ - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; if (!clixon_err_category()) /* sanity: log if clixon_err() is not called ! */ clixon_log(h, LOG_NOTICE, "%s: Plugin '%s' callback does not make clixon_err call on error", __FUNCTION__, clixon_plugin_name_get(cp)); goto done; } - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; } retval = 0; @@ -842,17 +842,17 @@ plugin_transaction_commit_one(clixon_plugin_t *cp, if ((fn = clixon_plugin_api_get(cp)->ca_trans_commit) != NULL){ wh = NULL; - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; if (fn(h, (transaction_data)td) < 0){ - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; if (!clixon_err_category()) /* sanity: log if clixon_err() is not called ! */ clixon_log(h, LOG_NOTICE, "%s: Plugin '%s' callback does not make clixon_err call on error", __FUNCTION__, clixon_plugin_name_get(cp)); goto done; } - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; } retval = 0; @@ -910,17 +910,17 @@ plugin_transaction_commit_done_one(clixon_plugin_t *cp, if ((fn = clixon_plugin_api_get(cp)->ca_trans_commit_done) != NULL){ wh = NULL; - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; if (fn(h, (transaction_data)td) < 0){ - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; if (!clixon_err_category()) /* sanity: log if clixon_err() is not called ! */ clixon_log(h, LOG_NOTICE, "%s: Plugin '%s' callback does not make clixon_err call on error", __FUNCTION__, clixon_plugin_name_get(cp)); goto done; } - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; } retval = 0; @@ -971,17 +971,17 @@ plugin_transaction_end_one(clixon_plugin_t *cp, if ((fn = clixon_plugin_api_get(cp)->ca_trans_end) != NULL){ wh = NULL; - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; if (fn(h, (transaction_data)td) < 0){ - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; if (!clixon_err_category()) /* sanity: log if clixon_err() is not called ! */ clixon_log(h, LOG_NOTICE, "%s: Plugin '%s' callback does not make clixon_err call on error", __FUNCTION__, clixon_plugin_name_get(cp)); goto done; } - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; } retval = 0; @@ -1024,17 +1024,17 @@ plugin_transaction_abort_one(clixon_plugin_t *cp, if ((fn = clixon_plugin_api_get(cp)->ca_trans_abort) != NULL){ wh = NULL; - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; if (fn(h, (transaction_data)td) < 0){ - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; if (!clixon_err_category()) /* sanity: log if clixon_err() is not called ! */ clixon_log(h, LOG_NOTICE, "%s: Plugin '%s' callback does not make clixon_err call on error", __FUNCTION__, clixon_plugin_name_get(cp)); goto done; } - if (plugin_context_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, clixon_plugin_name_get(cp), __FUNCTION__) < 0) goto done; } retval = 0; diff --git a/apps/cli/cli_handle.c b/apps/cli/cli_handle.c index 2c46c702..c72637a7 100644 --- a/apps/cli/cli_handle.c +++ b/apps/cli/cli_handle.c @@ -107,7 +107,7 @@ cli_handle_init(void) goto done; } cligen_userhandle_set(clih, cl); - cligen_eval_wrap_fn_set(clih, plugin_context_check, cl); + cligen_eval_wrap_fn_set(clih, clixon_resource_check, cl); cl->cl_cligen = clih; h = (clixon_handle)cl; diff --git a/lib/clixon/clixon_plugin.h b/lib/clixon/clixon_plugin.h index b03d53ce..7983d830 100644 --- a/lib/clixon/clixon_plugin.h +++ b/lib/clixon/clixon_plugin.h @@ -480,8 +480,6 @@ int clixon_plugins_load(clixon_handle h, const char *function, const char *dir, int clixon_pseudo_plugin(clixon_handle h, const char *name, clixon_plugin_t **cpp); -int plugin_context_check(clixon_handle h, void **wh, const char *name, const char *fn); - int clixon_plugin_start_one(clixon_plugin_t *cp, clixon_handle h); int clixon_plugin_start_all(clixon_handle h); diff --git a/lib/clixon/clixon_proc.h b/lib/clixon/clixon_proc.h index 99bfc33f..3387545b 100644 --- a/lib/clixon/clixon_proc.h +++ b/lib/clixon/clixon_proc.h @@ -76,5 +76,6 @@ int clixon_process_operation(clixon_handle h, const char *name, proc_operation o int clixon_process_status(clixon_handle h, const char *name, cbuf *cbret); int clixon_process_start_all(clixon_handle h); int clixon_process_waitpid(clixon_handle h); +int clixon_resource_check(clixon_handle h, void **wh, const char *name, const char *fn); #endif /* _CLIXON_PROC_H_ */ diff --git a/lib/src/clixon_plugin.c b/lib/src/clixon_plugin.c index 17a03275..06ee20f0 100644 --- a/lib/src/clixon_plugin.c +++ b/lib/src/clixon_plugin.c @@ -48,7 +48,6 @@ #include #include #include -#include #include #include @@ -72,21 +71,12 @@ #include "clixon_yang_module.h" #include "clixon_netconf_lib.h" #include "clixon_validate.h" +#include "clixon_proc.h" #include "clixon_plugin.h" /* * Private types */ -/*! Structure for checking status before and after a plugin call - * - * Currently signal settings: blocked and handlers, and termios - * @see plugin_context_check - */ -struct plugin_context { - sigset_t pc_sigset; /* See sigprocmask(2) */ - struct sigaction pc_sigaction_vec[32]; /* See sigaction(2) */ - struct termios pc_termios; /* See termios(3) */ -}; /* Internal plugin structure with dlopen() handle and plugin_api * This is an internal type, not exposed in the API @@ -356,7 +346,7 @@ plugin_load_one(clixon_handle h, } clixon_err_reset(); wh = NULL; - if (plugin_context_check(h, &wh, file, __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, file, __FUNCTION__) < 0) goto done; if ((api = initfn(h)) == NULL) { if (!clixon_err_category()){ /* if clixon_err() is not called then log and continue */ @@ -369,7 +359,7 @@ plugin_load_one(clixon_handle h, goto done; } } - if (plugin_context_check(h, &wh, file, __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, file, __FUNCTION__) < 0) goto done; /* Note: sizeof clixon_plugin_api which is largest of clixon_plugin_api:s */ @@ -504,184 +494,6 @@ done: return retval; } -/*! Get system context, eg signal procmask (for blocking) and sigactions - * - * Call this before a plugin - * @retval pc Plugin context structure, use free() to deallocate - * @retval NULL Error - * @see plugin_context_check - * */ -static void * -plugin_context_get(void) -{ - int i; - struct plugin_context *pc = NULL; - - if ((pc = malloc(sizeof(*pc))) == NULL){ - clixon_err(OE_UNIX, errno, "malloc"); - goto done; - } - memset(pc, 0, sizeof(*pc)); - if (sigprocmask(0, NULL, &pc->pc_sigset) < 0){ - clixon_err(OE_UNIX, errno, "sigprocmask"); - goto done; - } - for (i=1; i<32; i++){ - if (sigaction(i, NULL, &pc->pc_sigaction_vec[i]) < 0){ - clixon_err(OE_UNIX, errno, "sigaction"); - goto done; - } - /* Mask SA_RESTORER: Not intended for application use. - * Note that it may not be included in user space so may be hardcoded below - */ -#ifdef SA_RESTORER - pc->pc_sigaction_vec[i].sa_flags &= ~SA_RESTORER; -#else - pc->pc_sigaction_vec[i].sa_flags &= ~0x04000000; -#endif - } - if (isatty(0) && tcgetattr(0, &pc->pc_termios) < 0){ - clixon_err(OE_UNIX, errno, "tcgetattr %d", errno); - goto done; - } - return pc; - done: - if (pc) - free(pc); - return NULL; -} - -/*! Given an existing, old plugin context, check if anything has changed - * - * Called twice: - * 1) Make a check of resources - * 2) Make a new check and compare with the old check, return 1 on success, 0 on fail - * Log if there is a difference at loglevel WARNING. - * Controlled by CLICON_PLUGIN_CALLBACK_CHECK: - * 0 : No checks - * 1 : warning logs on failure - * 2 : log and abort on failure - * - * @param[in] h Clixon handle - * @param[in,out] wh Either: NULL for init, will be assigned, OR previous handle (will be freed) - * @param[in] name Name of plugin for logging. Can be other name, context dependent - * @param[in] fn Typically name of callback, or caller function - * @retval 1 OK - * @retval 0 Fail, log on syslog using LOG_WARNING - * @retval -1 Error - * @note Only logs error, does not generate error - * @note name and fn are context dependent, since the env of callback calls are very different - * @see plugin_context_get - * @see CLICON_PLUGIN_CALLBACK_CHECK Enable to activate these checks - */ -int -plugin_context_check(clixon_handle h, - void **wh, - const char *name, - const char *fn) -{ - int retval = -1; - int failed = 0; - int i; - struct plugin_context *oldpc; - struct plugin_context *newpc = NULL; - int option; - - if (h == NULL){ - errno = EINVAL; - return -1; - } - option = clicon_option_int(h, "CLICON_PLUGIN_CALLBACK_CHECK"); - /* Check if plugion checks are enabled */ - if (option == 0) - return 1; - if (wh == NULL){ - errno = EINVAL; - return -1; - } - if (*wh == NULL){ - *wh = plugin_context_get(); - return 1; - } - oldpc = (struct plugin_context *)*wh; - if ((newpc = plugin_context_get()) == NULL) - goto done; - if (oldpc->pc_termios.c_iflag != newpc->pc_termios.c_iflag){ - clixon_log(h, LOG_WARNING, "%s Plugin context %s %s: Changed termios input modes from 0x%x to 0x%x", __FUNCTION__, - name, fn, - oldpc->pc_termios.c_iflag, - newpc->pc_termios.c_iflag); - failed++; - } - if (oldpc->pc_termios.c_oflag != newpc->pc_termios.c_oflag){ - clixon_log(h, LOG_WARNING, "%s Plugin context %s %s: Changed termios output modes from 0x%x to 0x%x", __FUNCTION__, - name, fn, - oldpc->pc_termios.c_oflag, - newpc->pc_termios.c_oflag); - failed++; - } - if (oldpc->pc_termios.c_cflag != newpc->pc_termios.c_cflag){ - clixon_log(h, LOG_WARNING, "%s Plugin context %s %s: Changed termios control modes from 0x%x to 0x%x", __FUNCTION__, - name, fn, - oldpc->pc_termios.c_cflag, - newpc->pc_termios.c_cflag); - failed++; - } - if (oldpc->pc_termios.c_lflag != newpc->pc_termios.c_lflag){ - clixon_log(h, LOG_WARNING, "%s Plugin context %s %s: Changed termios local modes from 0x%x to 0x%x", __FUNCTION__, - name, fn, - oldpc->pc_termios.c_lflag, - newpc->pc_termios.c_lflag); - failed++; - } - /* XXX pc_termios.cc_t c_cc[NCCS] not checked */ - /* Abort if option is 2 or above on failure - */ - if (option > 1 && failed) - abort(); - for (i=1; i<32; i++){ - if (sigismember(&oldpc->pc_sigset, i) != sigismember(&newpc->pc_sigset, i)){ - clixon_log(h, LOG_WARNING, "%s Plugin context %s %s: Changed blocking of signal %s(%d) from %d to %d", __FUNCTION__, - name, fn, strsignal(i), i, - sigismember(&oldpc->pc_sigset, i), - sigismember(&newpc->pc_sigset, i) - ); - failed++; - } - if (oldpc->pc_sigaction_vec[i].sa_flags != newpc->pc_sigaction_vec[i].sa_flags){ - clixon_log(h, LOG_WARNING, "%s Plugin context %s %s: Changed flags of signal %s(%d) from 0x%x to 0x%x", __FUNCTION__, - name, fn, strsignal(i), i, - oldpc->pc_sigaction_vec[i].sa_flags, - newpc->pc_sigaction_vec[i].sa_flags);; - failed++; - } - if (oldpc->pc_sigaction_vec[i].sa_sigaction != newpc->pc_sigaction_vec[i].sa_sigaction){ - clixon_log(h, LOG_WARNING, "%s Plugin context %s %s: Changed action of signal %s(%d) from %p to %p", __FUNCTION__, - name, fn, strsignal(i), i, - oldpc->pc_sigaction_vec[i].sa_sigaction, - newpc->pc_sigaction_vec[i].sa_sigaction); - failed++; - } - /* Abort if option is 2 or above on failure - */ - if (option > 1 && failed) - abort(); - } - if (failed) - goto fail; - retval = 1; /* OK */ - done: - if (newpc) - free(newpc); - if (oldpc) - free(oldpc); - if (wh && *wh) - *wh = NULL; - return retval; - fail: - retval = 0; - goto done; -} /*! Call single plugin start callback * @@ -700,7 +512,7 @@ clixon_plugin_start_one(clixon_plugin_t *cp, if ((fn = cp->cp_api.ca_start) != NULL){ wh = NULL; - if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) goto done; if (fn(h) < 0) { if (clixon_err_category() < 0) @@ -708,7 +520,7 @@ clixon_plugin_start_one(clixon_plugin_t *cp, __FUNCTION__, cp->cp_name); goto done; } - if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) goto done; } retval = 0; @@ -758,7 +570,7 @@ clixon_plugin_exit_one(clixon_plugin_t *cp, if ((fn = cp->cp_api.ca_exit) != NULL){ wh = NULL; - if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) goto done; if (fn(h) < 0) { if (clixon_err_category() < 0) @@ -766,7 +578,7 @@ clixon_plugin_exit_one(clixon_plugin_t *cp, __FUNCTION__, cp->cp_name); goto done; } - if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) goto done; if (dlclose(cp->cp_handle) != 0) { error = (char*)dlerror(); @@ -833,7 +645,7 @@ clixon_plugin_auth_one(clixon_plugin_t *cp, clixon_debug(CLIXON_DBG_DEFAULT, "%s", __FUNCTION__); if ((fn = cp->cp_api.ca_auth) != NULL){ wh = NULL; - if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) goto done; if ((retval = fn(h, req, auth_type, authp)) < 0) { if (clixon_err_category() < 0) @@ -841,7 +653,7 @@ clixon_plugin_auth_one(clixon_plugin_t *cp, __FUNCTION__, cp->cp_name); goto done; } - if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) goto done; } else @@ -918,7 +730,7 @@ clixon_plugin_extension_one(clixon_plugin_t *cp, if ((fn = cp->cp_api.ca_extension) != NULL){ wh = NULL; - if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) goto done; if (fn(h, yext, ys) < 0) { if (clixon_err_category() < 0) @@ -926,7 +738,7 @@ clixon_plugin_extension_one(clixon_plugin_t *cp, __FUNCTION__, cp->cp_name); goto done; } - if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) goto done; } retval = 0; @@ -989,7 +801,7 @@ clixon_plugin_datastore_upgrade_one(clixon_plugin_t *cp, if ((fn = cp->cp_api.ca_datastore_upgrade) != NULL){ wh = NULL; - if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) goto done; if (fn(h, db, xt, msd) < 0) { if (clixon_err_category() < 0) @@ -997,7 +809,7 @@ clixon_plugin_datastore_upgrade_one(clixon_plugin_t *cp, __FUNCTION__, cp->cp_name); goto done; } - if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) goto done; } retval = 0; @@ -1060,7 +872,7 @@ clixon_plugin_yang_mount_one(clixon_plugin_t *cp, if ((fn = cp->cp_api.ca_yang_mount) != NULL){ wh = NULL; - if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) goto done; if (fn(h, xt, config, vl, yanglib) < 0) { if (clixon_err_category() < 0) @@ -1068,7 +880,7 @@ clixon_plugin_yang_mount_one(clixon_plugin_t *cp, __FUNCTION__, cp->cp_name); goto done; } - if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) goto done; } retval = 0; @@ -1127,7 +939,7 @@ clixon_plugin_yang_patch_one(clixon_plugin_t *cp, if ((fn = cp->cp_api.ca_yang_patch) != NULL){ wh = NULL; - if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) goto done; if (fn(h, ymod) < 0) { if (clixon_err_category() < 0) @@ -1135,7 +947,7 @@ clixon_plugin_yang_patch_one(clixon_plugin_t *cp, __FUNCTION__, cp->cp_name); goto done; } - if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) goto done; } retval = 0; @@ -1187,7 +999,7 @@ clixon_plugin_netconf_errmsg_one(clixon_plugin_t *cp, if ((fn = cp->cp_api.ca_errmsg) != NULL){ wh = NULL; - if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) goto done; if (fn(h, xerr, cberr) < 0) { if (clixon_err_category() < 0) @@ -1195,7 +1007,7 @@ clixon_plugin_netconf_errmsg_one(clixon_plugin_t *cp, __FUNCTION__, cp->cp_name); goto done; } - if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) goto done; } retval = 0; @@ -1247,7 +1059,7 @@ clixon_plugin_version_one(clixon_plugin_t *cp, if ((fn = cp->cp_api.ca_version) != NULL){ wh = NULL; - if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) goto done; if (fn(h, f) < 0) { if (clixon_err_category() < 0) @@ -1255,7 +1067,7 @@ clixon_plugin_version_one(clixon_plugin_t *cp, __FUNCTION__, cp->cp_name); goto done; } - if (plugin_context_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, cp->cp_name, __FUNCTION__) < 0) goto done; } retval = 0; @@ -1424,16 +1236,16 @@ rpc_callback_call(clixon_handle h, ns && rc->rc_namespace && strcmp(rc->rc_namespace, ns) == 0){ wh = NULL; - if (plugin_context_check(h, &wh, rc->rc_name, __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, rc->rc_name, __FUNCTION__) < 0) goto done; if (rc->rc_callback(h, xe, cbret, arg, rc->rc_arg) < 0){ clixon_debug(CLIXON_DBG_DEFAULT, "%s Error in: %s", __FUNCTION__, rc->rc_name); - if (plugin_context_check(h, &wh, rc->rc_name, __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, rc->rc_name, __FUNCTION__) < 0) goto done; goto done; } nr++; - if (plugin_context_check(h, &wh, rc->rc_name, __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, rc->rc_name, __FUNCTION__) < 0) goto done; } rc = NEXTQ(rpc_callback_t *, rc); @@ -1551,16 +1363,16 @@ action_callback_call(clixon_handle h, if ((rc = (rpc_callback_t *)yang_action_cb_get(ya)) != NULL){ do { if (strcmp(rc->rc_name, name) == 0){ - if (plugin_context_check(h, &wh, rc->rc_name, __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, rc->rc_name, __FUNCTION__) < 0) goto done; if (rc->rc_callback(h, xa, cbret, arg, rc->rc_arg) < 0){ clixon_debug(CLIXON_DBG_DEFAULT, "%s Error in: %s", __FUNCTION__, rc->rc_name); - if (plugin_context_check(h, &wh, rc->rc_name, __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, rc->rc_name, __FUNCTION__) < 0) goto done; goto done; } nr++; - if (plugin_context_check(h, &wh, rc->rc_name, __FUNCTION__) < 0) + if (clixon_resource_check(h, &wh, rc->rc_name, __FUNCTION__) < 0) goto done; } rc = NEXTQ(rpc_callback_t *, rc); diff --git a/lib/src/clixon_proc.c b/lib/src/clixon_proc.c index 08d34cb0..e5fab217 100644 --- a/lib/src/clixon_proc.c +++ b/lib/src/clixon_proc.c @@ -96,6 +96,7 @@ #include #include #include +#include #ifdef HAVE_SETNS /* linux network namespaces */ #include /* setns / unshare */ #endif @@ -159,6 +160,17 @@ struct process_entry_t { proc_cb_t *pe_callback; /* Wrapper function, may be called from process_operation */ }; +/*! Structure for checking resources before and after a call + * + * Currently signal settings: blocked and handlers, and termios + * @see clixon_resource_check + */ +struct resource_context { + sigset_t rc_sigset; /* See sigprocmask(2) */ + struct sigaction rc_sigaction_vec[32]; /* See sigaction(2) */ + struct termios rc_termios; /* See termios(3) */ +}; + /* Forward declaration */ static int clixon_process_sched_register(clixon_handle h, int delay); static int clixon_process_delete_only(process_entry_t *pe); @@ -1100,3 +1112,181 @@ clixon_process_waitpid(clixon_handle h) clixon_debug(CLIXON_DBG_DEFAULT, "%s retval:%d", __FUNCTION__, retval); return retval; } + +/*! Get system context, eg signal procmask (for blocking) and sigactions + * + * Call this before a plugin + * @retval pc Plugin context structure, use free() to deallocate + * @retval NULL Error + * */ +static void * +resource_context_get(void) +{ + int i; + struct resource_context *rc = NULL; + + if ((rc = malloc(sizeof(*rc))) == NULL){ + clixon_err(OE_UNIX, errno, "malloc"); + goto done; + } + memset(rc, 0, sizeof(*rc)); + if (sigprocmask(0, NULL, &rc->rc_sigset) < 0){ + clixon_err(OE_UNIX, errno, "sigprocmask"); + goto done; + } + for (i=1; i<32; i++){ + if (sigaction(i, NULL, &rc->rc_sigaction_vec[i]) < 0){ + clixon_err(OE_UNIX, errno, "sigaction"); + goto done; + } + /* Mask SA_RESTORER: Not intended for application use. + * Note that it may not be included in user space so may be hardcoded below + */ +#ifdef SA_RESTORER + rc->rc_sigaction_vec[i].sa_flags &= ~SA_RESTORER; +#else + rc->rc_sigaction_vec[i].sa_flags &= ~0x04000000; +#endif + } + if (isatty(0) && tcgetattr(0, &rc->rc_termios) < 0){ + clixon_err(OE_UNIX, errno, "tcgetattr %d", errno); + goto done; + } + return rc; + done: + if (rc) + free(rc); + return NULL; +} + +/*! Check terminal+signal context, check if anything has changed + * + * Called twice: + * 1) Make a check of resources + * 2) Make a new check and compare with the old check, return 1 on success, 0 on fail + * Log if there is a difference at loglevel WARNING. + * Controlled by CLICON_PLUGIN_CALLBACK_CHECK: + * 0 : No checks + * 1 : warning logs on failure + * 2 : log and abort on failure + * + * @param[in] h Clixon handle + * @param[in,out] wh Either: NULL for init, will be assigned, OR previous handle (will be freed) + * @param[in] name Name of plugin for logging. Can be other name, context dependent + * @param[in] fn Typically name of callback, or caller function + * @retval 1 OK + * @retval 0 Fail, log on syslog using LOG_WARNING + * @retval -1 Error + * @note Only logs error, does not generate error + * @note name and fn are context dependent, since the env of callback calls are very different + * @see CLICON_PLUGIN_CALLBACK_CHECK Enable to activate these checks + * The naming "PLUGIN" is of historical reasons. + */ +int +clixon_resource_check(clixon_handle h, + void **wh, + const char *name, + const char *fn) +{ + int retval = -1; + int failed = 0; + int i; + struct resource_context *oldrc; + struct resource_context *newrc = NULL; + int option; + + if (h == NULL){ + errno = EINVAL; + return -1; + } + option = clicon_option_int(h, "CLICON_PLUGIN_CALLBACK_CHECK"); + /* Check if plugion checks are enabled */ + if (option == 0) + return 1; + if (wh == NULL){ + errno = EINVAL; + return -1; + } + if (*wh == NULL){ + *wh = resource_context_get(); + return 1; + } + oldrc = (struct resource_context *)*wh; + if ((newrc = resource_context_get()) == NULL) + goto done; + if (oldrc->rc_termios.c_iflag != newrc->rc_termios.c_iflag){ + clixon_log(h, LOG_WARNING, "%s Plugin context %s %s: Changed termios input modes from 0x%x to 0x%x", __FUNCTION__, + name, fn, + oldrc->rc_termios.c_iflag, + newrc->rc_termios.c_iflag); + failed++; + } + if (oldrc->rc_termios.c_oflag != newrc->rc_termios.c_oflag){ + clixon_log(h, LOG_WARNING, "%s Plugin context %s %s: Changed termios output modes from 0x%x to 0x%x", __FUNCTION__, + name, fn, + oldrc->rc_termios.c_oflag, + newrc->rc_termios.c_oflag); + failed++; + } + if (oldrc->rc_termios.c_cflag != newrc->rc_termios.c_cflag){ + clixon_log(h, LOG_WARNING, "%s Plugin context %s %s: Changed termios control modes from 0x%x to 0x%x", __FUNCTION__, + name, fn, + oldrc->rc_termios.c_cflag, + newrc->rc_termios.c_cflag); + failed++; + } + if (oldrc->rc_termios.c_lflag != newrc->rc_termios.c_lflag){ + clixon_log(h, LOG_WARNING, "%s Plugin context %s %s: Changed termios local modes from 0x%x to 0x%x", __FUNCTION__, + name, fn, + oldrc->rc_termios.c_lflag, + newrc->rc_termios.c_lflag); + failed++; + } + /* XXX rc_termios.cc_t c_cc[NCCS] not checked */ + /* Abort if option is 2 or above on failure + */ + if (option > 1 && failed) + abort(); + for (i=1; i<32; i++){ + if (sigismember(&oldrc->rc_sigset, i) != sigismember(&newrc->rc_sigset, i)){ + clixon_log(h, LOG_WARNING, "%s Plugin context %s %s: Changed blocking of signal %s(%d) from %d to %d", __FUNCTION__, + name, fn, strsignal(i), i, + sigismember(&oldrc->rc_sigset, i), + sigismember(&newrc->rc_sigset, i) + ); + failed++; + } + if (oldrc->rc_sigaction_vec[i].sa_flags != newrc->rc_sigaction_vec[i].sa_flags){ + clixon_log(h, LOG_WARNING, "%s Plugin context %s %s: Changed flags of signal %s(%d) from 0x%x to 0x%x", __FUNCTION__, + name, fn, strsignal(i), i, + oldrc->rc_sigaction_vec[i].sa_flags, + newrc->rc_sigaction_vec[i].sa_flags);; + failed++; + } + if (oldrc->rc_sigaction_vec[i].sa_sigaction != newrc->rc_sigaction_vec[i].sa_sigaction){ + clixon_log(h, LOG_WARNING, "%s Plugin context %s %s: Changed action of signal %s(%d) from %p to %p", __FUNCTION__, + name, fn, strsignal(i), i, + oldrc->rc_sigaction_vec[i].sa_sigaction, + newrc->rc_sigaction_vec[i].sa_sigaction); + failed++; + } + /* Abort if option is 2 or above on failure + */ + if (option > 1 && failed) + abort(); + } + if (failed) + goto fail; + retval = 1; /* OK */ + done: + if (newrc) + free(newrc); + if (oldrc) + free(oldrc); + if (wh && *wh) + *wh = NULL; + return retval; + fail: + retval = 0; + goto done; +} diff --git a/lib/src/clixon_proto.c b/lib/src/clixon_proto.c index d3d929fd..788333f1 100644 --- a/lib/src/clixon_proto.c +++ b/lib/src/clixon_proto.c @@ -56,6 +56,7 @@ #include #include #include +#include #include #include #include @@ -402,7 +403,8 @@ clicon_msg_send(int s, * @param[out] eof Set if eof encountered * @retval 0 OK * @retval -1 Error - * Note: caller must ensure that s is closed if eof is set after call. + * @note: Caller must ensure that s is closed if eof is set after call. + * @note: intr parameter used in eg CLI where receive should be interruptable * @see clicon_msg_rcv1 using plain NETCONF */ int @@ -416,14 +418,18 @@ clicon_msg_rcv(int s, struct clicon_msg hdr; int hlen; ssize_t len2; - sigfn_t oldhandler; uint32_t mlen; + sigset_t oldsigset; + struct sigaction oldsigaction[32] = {{{0,},},}; clixon_debug(CLIXON_DBG_DETAIL, "%s", __FUNCTION__); *eof = 0; if (intr){ + if (clixon_signal_save(&oldsigset, oldsigaction) < 0) + goto done; + set_signal(SIGINT, SIG_IGN, NULL); clicon_signal_unblock(SIGINT); - set_signal_flags(SIGINT, 0, atomicio_sig_handler, &oldhandler); + set_signal_flags(SIGINT, 0, atomicio_sig_handler, NULL); } if ((hlen = atomicio(read, s, &hdr, sizeof(hdr))) < 0){ if (intr && _atomicio_sig) @@ -481,8 +487,8 @@ clicon_msg_rcv(int s, done: clixon_debug(CLIXON_DBG_DETAIL, "%s retval:%d", __FUNCTION__, retval); if (intr){ - set_signal(SIGINT, oldhandler, NULL); - clicon_signal_block(SIGINT); + if (clixon_signal_restore(&oldsigset, oldsigaction) < 0) + goto done; } return retval; } diff --git a/lib/src/clixon_yang_schema_mount.c b/lib/src/clixon_yang_schema_mount.c index 2003d531..c9b685da 100644 --- a/lib/src/clixon_yang_schema_mount.c +++ b/lib/src/clixon_yang_schema_mount.c @@ -161,7 +161,7 @@ yang_mount_get(yang_stmt *y, cvec *cvv; cg_var *cv; - clixon_debug(CLIXON_DBG_DEFAULT, "%s %s %p", __FUNCTION__, xpath, y); + clixon_debug(CLIXON_DBG_DETAIL, "%s %s %p", __FUNCTION__, xpath, y); /* Special value in yang unknown node for mount-points: mapping from xpath->mounted yspec */ if ((cvv = yang_cvec_get(y)) != NULL && (cv = cvec_find(cvv, xpath)) != NULL &&