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.
This commit is contained in:
parent
7b2906de24
commit
cbc894ed7b
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue