From cbc894ed7b07f7eea34acfea62c728bdf182918f Mon Sep 17 00:00:00 2001 From: Zachary T Welch Date: Sun, 29 Nov 2009 18:39:13 -0800 Subject: [PATCH] command output capture: do not use interp global Adds a log_capture_state structure to pass to the log capture callback used by the command module. Ensures that the capture occurs in the proper context. --- src/helper/command.c | 49 ++++++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/src/helper/command.c b/src/helper/command.c index 5df4a453..607693cc 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -52,30 +52,50 @@ Jim_Interp *interp = NULL; static int run_command(struct command_context *context, struct command *c, const char *words[], unsigned num_words); +struct log_capture_state { + Jim_Interp *interp; + Jim_Obj *output; +}; + static void tcl_output(void *privData, const char *file, unsigned line, const char *function, const char *string) { - Jim_Obj *tclOutput = (Jim_Obj *)privData; - Jim_AppendString(interp, tclOutput, string, strlen(string)); + struct log_capture_state *state = (struct log_capture_state *)privData; + Jim_AppendString(state->interp, state->output, string, strlen(string)); } -static Jim_Obj *command_log_capture_start(Jim_Interp *interp) +static struct log_capture_state *command_log_capture_start(Jim_Interp *interp) { /* capture log output and return it. A garbage collect can * happen, so we need a reference count to this object */ Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0); if (NULL == tclOutput) return NULL; + + struct log_capture_state *state = malloc(sizeof(*state)); + if (NULL == state) + return NULL; + + state->interp = interp; Jim_IncrRefCount(tclOutput); - log_add_callback(tcl_output, tclOutput); - return tclOutput; + state->output = tclOutput; + + log_add_callback(tcl_output, state); + + return state; } -static void command_log_capture_finish(Jim_Interp *interp, Jim_Obj *tclOutput) +static void command_log_capture_finish(struct log_capture_state *state) { - log_remove_callback(tcl_output, tclOutput); - Jim_SetResult(interp, tclOutput); - Jim_DecrRefCount(interp, tclOutput); + if (NULL == state) + return; + + log_remove_callback(tcl_output, state); + + Jim_SetResult(state->interp, state->output); + Jim_DecrRefCount(state->interp, state->output); + + free(state); } static int command_retval_set(Jim_Interp *interp, int retval) @@ -164,15 +184,14 @@ static int script_command_run(Jim_Interp *interp, if (NULL == words) return JIM_ERR; - Jim_Obj *tclOutput = NULL; + struct log_capture_state *state = NULL; if (capture) - tclOutput = command_log_capture_start(interp); + state = command_log_capture_start(interp); struct command_context *cmd_ctx = current_command_context(); int retval = run_command(cmd_ctx, c, (const char **)words, nwords); - if (capture) - command_log_capture_finish(interp, tclOutput); + command_log_capture_finish(state); script_command_args_free(words, nwords); return command_retval_set(interp, retval); @@ -804,12 +823,12 @@ static int jim_capture(Jim_Interp *interp, int argc, Jim_Obj *const *argv) if (argc != 2) return JIM_ERR; - Jim_Obj *tclOutput = command_log_capture_start(interp); + struct log_capture_state *state = command_log_capture_start(interp); const char *str = Jim_GetString(argv[1], NULL); int retcode = Jim_Eval_Named(interp, str, __THIS__FILE__, __LINE__); - command_log_capture_finish(interp, tclOutput); + command_log_capture_finish(state); return retcode; } -- 2.39.5