Plugin-context: moved status field from struct to function retval

This commit is contained in:
Olof hagsand 2021-10-20 11:17:14 +02:00
parent c93348d8d5
commit 7d7024d114
2 changed files with 48 additions and 21 deletions

View file

@ -68,7 +68,9 @@ Developers may need to change their code
### Minor features ### Minor features
* Added checks of changed handlers or blocked signal after plugin function calls * Plugin context check before and after all callbacks.
* Check blocked signals and signal handlers
* Any changes to context are logged at loglevel WARNING
* Added set/get pointer API to clixon_data: * Added set/get pointer API to clixon_data:
* clicon_ptr_get(), clicon_ptr_set(), * clicon_ptr_get(), clicon_ptr_set(),
* Restconf YANG PATCH according to RFC 8072 * Restconf YANG PATCH according to RFC 8072

View file

@ -77,7 +77,6 @@
struct plugin_context { struct plugin_context {
sigset_t pc_sigset; /* See sigprocmask(2) */ sigset_t pc_sigset; /* See sigprocmask(2) */
struct sigaction pc_sigaction_vec[32]; /* See sigaction(2) */ struct sigaction pc_sigaction_vec[32]; /* See sigaction(2) */
int pc_status; /* 0: OK, -1: fail */
}; };
/* Internal plugin structure with dlopen() handle and plugin_api /* Internal plugin structure with dlopen() handle and plugin_api
@ -514,10 +513,11 @@ plugin_context_get(void)
int i; int i;
struct plugin_context *pc = NULL; struct plugin_context *pc = NULL;
if ((pc = malloc(sizeof *pc)) == NULL){ if ((pc = malloc(sizeof(*pc))) == NULL){
clicon_err(OE_UNIX, errno, "malloc"); clicon_err(OE_UNIX, errno, "malloc");
goto done; goto done;
} }
memset(pc, 0, sizeof(*pc));
if (sigprocmask(0, NULL, &pc->pc_sigset) < 0){ if (sigprocmask(0, NULL, &pc->pc_sigset) < 0){
clicon_err(OE_UNIX, errno, "sigprocmask"); clicon_err(OE_UNIX, errno, "sigprocmask");
goto done; goto done;
@ -543,12 +543,19 @@ plugin_context_get(void)
return NULL; return NULL;
} }
/*! Given an existing, old plugin context, check if anytjing has changed /*! Given an existing, old plugin context, check if anything has changed
* @param[in,out] oldpc Old plugin context, status will be returned inside oldpc *
* @param[in] name Name of plugin for logging * Make a new check and compare with the old (procided as in-parameter).
* @param[in] fn Name of callback * Log if there is a difference at loglevel WARNING.
* You can modify the code to also fail with assert if you want early fail.
*
* @param[in,out] oldpc Old plugin context
* @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 Error * @retval -1 Error
* @retval 0 OK * @retval 0 Fail, log on syslog using LOG_WARNING
* @retval 1 OK
* @note name and fn are context dependent, since the env of callback calls are very different
* @see plugin_context_get * @see plugin_context_get
*/ */
int int
@ -567,7 +574,7 @@ plugin_context_check(plugin_context_t *oldpc0,
for (i=1; i<32; i++){ for (i=1; i<32; i++){
failed = 0; failed = 0;
if (sigismember(&oldpc->pc_sigset, i) != sigismember(&newpc->pc_sigset, i)){ if (sigismember(&oldpc->pc_sigset, i) != sigismember(&newpc->pc_sigset, i)){
clicon_log(LOG_WARNING, "%s Plugin %s %s: Changed blocking of signal %s(%d) from %d to %d", __FUNCTION__, clicon_log(LOG_WARNING, "%s Plugin context %s %s: Changed blocking of signal %s(%d) from %d to %d", __FUNCTION__,
name, fn, strsignal(i), i, name, fn, strsignal(i), i,
sigismember(&oldpc->pc_sigset, i), sigismember(&oldpc->pc_sigset, i),
sigismember(&newpc->pc_sigset, i) sigismember(&newpc->pc_sigset, i)
@ -575,29 +582,36 @@ plugin_context_check(plugin_context_t *oldpc0,
failed++; failed++;
} }
if (oldpc->pc_sigaction_vec[i].sa_flags != newpc->pc_sigaction_vec[i].sa_flags){ if (oldpc->pc_sigaction_vec[i].sa_flags != newpc->pc_sigaction_vec[i].sa_flags){
clicon_log(LOG_WARNING, "%s Plugin %s %s: Changed flags of signal %s(%d) from 0x%x to 0x%x", __FUNCTION__, clicon_log(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, name, fn, strsignal(i), i,
oldpc->pc_sigaction_vec[i].sa_flags, oldpc->pc_sigaction_vec[i].sa_flags,
newpc->pc_sigaction_vec[i].sa_flags);; newpc->pc_sigaction_vec[i].sa_flags);;
failed++; failed++;
} }
if (oldpc->pc_sigaction_vec[i].sa_sigaction != newpc->pc_sigaction_vec[i].sa_sigaction){ if (oldpc->pc_sigaction_vec[i].sa_sigaction != newpc->pc_sigaction_vec[i].sa_sigaction){
clicon_log(LOG_WARNING, "%s Plugin %s %s: Changed action of signal %s(%d) from %p to %p", __FUNCTION__, clicon_log(LOG_WARNING, "%s Plugin context %s %s: Changed action of signal %s(%d) from %p to %p", __FUNCTION__,
name, fn, strsignal(i), i, name, fn, strsignal(i), i,
oldpc->pc_sigaction_vec[i].sa_sigaction, oldpc->pc_sigaction_vec[i].sa_sigaction,
newpc->pc_sigaction_vec[i].sa_sigaction); newpc->pc_sigaction_vec[i].sa_sigaction);
failed++; failed++;
} }
if (failed){ #if 0
oldpc->pc_status = -1; /* In case you want early detection and crash. But otherwise it is recommended that
* the caller looks for retval == 0 */
assert(failed == 0);
#endif
if (failed)
goto fail;
} }
/* assert(oldpc->pc_status == 0); */ retval = 1; /* OK */
}
retval = 0;
done: done:
if (newpc) if (newpc)
free(newpc); free(newpc);
return retval; return retval;
fail:
retval = 0;
goto done;
} }
/*! Call single plugin start callback /*! Call single plugin start callback
@ -1064,6 +1078,7 @@ rpc_callback_call(clicon_handle h,
char *ns; char *ns;
int nr = 0; /* How many callbacks */ int nr = 0; /* How many callbacks */
plugin_module_struct *ms = plugin_module_struct_get(h); plugin_module_struct *ms = plugin_module_struct_get(h);
plugin_context_t *pc = NULL;
if (ms == NULL){ if (ms == NULL){
clicon_err(OE_PLUGIN, EINVAL, "plugin module not initialized"); clicon_err(OE_PLUGIN, EINVAL, "plugin module not initialized");
@ -1077,17 +1092,27 @@ rpc_callback_call(clicon_handle h,
if (strcmp(rc->rc_name, name) == 0 && if (strcmp(rc->rc_name, name) == 0 &&
ns && rc->rc_namespace && ns && rc->rc_namespace &&
strcmp(rc->rc_namespace, ns) == 0){ strcmp(rc->rc_namespace, ns) == 0){
if ((pc = plugin_context_get()) == NULL)
goto done;
if (rc->rc_callback(h, xe, cbret, arg, rc->rc_arg) < 0){ if (rc->rc_callback(h, xe, cbret, arg, rc->rc_arg) < 0){
clicon_debug(1, "%s Error in: %s", __FUNCTION__, rc->rc_name); clicon_debug(1, "%s Error in: %s", __FUNCTION__, rc->rc_name);
goto done; goto done;
} }
nr++; nr++;
if (plugin_context_check(pc, rc->rc_name, __FUNCTION__) < 0)
goto done;
if (pc){
free(pc);
pc = NULL;
}
} }
rc = NEXTQ(rpc_callback_t *, rc); rc = NEXTQ(rpc_callback_t *, rc);
} while (rc != ms->ms_rpc_callbacks); } while (rc != ms->ms_rpc_callbacks);
retval = nr; /* 0: none found, >0 nr of handlers called */ retval = nr; /* 0: none found, >0 nr of handlers called */
done: done:
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval); clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
if (pc)
free(pc);
return retval; return retval;
} }