Browse Source

Fix Jim interpreter memory leak

Change-Id: I71d7d97e7dc315c42fc43b65cb5fcecd7bdfb581
Signed-off-by: Marc Schink <openocd-dev@marcschink.de>
rtt
Marc Schink 8 years ago
parent
commit
e8f065c616
8 changed files with 91 additions and 19 deletions
  1. +6
    -2
      src/flash/nor/stellaris.c
  2. +41
    -8
      src/helper/command.c
  3. +17
    -1
      src/helper/command.h
  4. +4
    -1
      src/jtag/core.c
  5. +14
    -1
      src/server/server.c
  6. +3
    -1
      src/server/tcl_server.c
  7. +1
    -1
      src/target/dsp563xx.c
  8. +5
    -4
      src/target/target.c

+ 6
- 2
src/flash/nor/stellaris.c View File

@@ -1356,6 +1356,7 @@ COMMAND_HANDLER(stellaris_handle_recover_command)
{
struct flash_bank *bank;
int retval;
const char *tmp;

if (CMD_ARGC != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
@@ -1370,8 +1371,11 @@ COMMAND_HANDLER(stellaris_handle_recover_command)
* cycle to recover.
*/

Jim_Eval_Named(CMD_CTX->interp, "catch { hla_command \"debug unlock\" }", 0, 0);
if (!strcmp(Jim_GetString(Jim_GetResult(CMD_CTX->interp), NULL), "0")) {
Jim_Eval_Named(CMD_CTX->interp->interp,
"catch { hla_command \"debug unlock\" }", 0, 0);
tmp = Jim_GetString(Jim_GetResult(CMD_CTX->interp->interp), NULL);

if (!strcmp(tmp, "0")) {
retval = ERROR_OK;
goto user_action;
}


+ 41
- 8
src/helper/command.c View File

@@ -356,7 +356,7 @@ static int command_unknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
static int register_command_handler(struct command_context *cmd_ctx,
struct command *c)
{
Jim_Interp *interp = cmd_ctx->interp;
Jim_Interp *interp = cmd_ctx->interp->interp;
char *ocd_name = alloc_printf("ocd_%s", c->name);
if (NULL == ocd_name)
return JIM_ERR;
@@ -406,7 +406,7 @@ struct command *register_command(struct command_context *context,

int retval = ERROR_OK;
if (NULL != cr->jim_handler && NULL == parent) {
retval = Jim_CreateCommand(context->interp, cr->name,
retval = Jim_CreateCommand(context->interp->interp, cr->name,
cr->jim_handler, cr->jim_handler_data, NULL);
} else if (NULL != cr->handler || NULL != parent)
retval = register_command_handler(context, command_root(c));
@@ -643,7 +643,7 @@ int command_run_line(struct command_context *context, char *line)
* happen when the Jim Tcl interpreter is provided by eCos for
* instance.
*/
Jim_Interp *interp = context->interp;
Jim_Interp *interp = context->interp->interp;
Jim_DeleteAssocData(interp, "context");
retcode = Jim_SetAssocData(interp, "context", NULL, context);
if (retcode == JIM_OK) {
@@ -720,8 +720,14 @@ void command_set_output_handler(struct command_context *context,

struct command_context *copy_command_context(struct command_context *context)
{
struct command_context *copy_context = malloc(sizeof(struct command_context));
struct command_context *copy_context;

copy_context = malloc(sizeof(struct command_context));

if (!copy_context)
return NULL;

context->interp->refcnt++;
*copy_context = *context;

return copy_context;
@@ -729,9 +735,18 @@ struct command_context *copy_command_context(struct command_context *context)

void command_done(struct command_context *cmd_ctx)
{
if (NULL == cmd_ctx)
if (cmd_ctx == NULL)
return;

cmd_ctx->interp->refcnt--;

if (!cmd_ctx->interp->refcnt) {
if (cmd_ctx->interp->free)
Jim_FreeInterp(cmd_ctx->interp->interp);

free(cmd_ctx->interp);
}

free(cmd_ctx);
}

@@ -1269,14 +1284,28 @@ static const struct command_registration command_builtin_handlers[] = {

struct command_context *command_init(const char *startup_tcl, Jim_Interp *interp)
{
struct command_context *context = malloc(sizeof(struct command_context));
struct command_context *context;
const char *HostOs;

context = malloc(sizeof(struct command_context));

if (!context) {
LOG_ERROR("Failed to allocate command context.");
return NULL;
}

context->mode = COMMAND_EXEC;
context->commands = NULL;
context->current_target = 0;
context->output_handler = NULL;
context->output_handler_priv = NULL;
context->interp = malloc(sizeof(struct command_interpreter));

if (!context->interp) {
LOG_ERROR("Failed to allocate command interpreter.");
free(context);
return NULL;
}

/* Create a jim interpreter if we were not handed one */
if (interp == NULL) {
@@ -1285,9 +1314,13 @@ struct command_context *command_init(const char *startup_tcl, Jim_Interp *interp
/* Add all the Jim core commands */
Jim_RegisterCoreCommands(interp);
Jim_InitStaticExtensions(interp);
context->interp->free = true;
} else {
context->interp->free = false;
}

context->interp = interp;
context->interp->interp = interp;
context->interp->refcnt = 1;

/* Stick to lowercase for HostOS strings. */
#if defined(_MSC_VER)
@@ -1355,7 +1388,7 @@ void process_jim_events(struct command_context *cmd_ctx)
return;

recursion++;
Jim_ProcessEvents(cmd_ctx->interp, JIM_ALL_EVENTS | JIM_DONT_WAIT);
Jim_ProcessEvents(cmd_ctx->interp->interp, JIM_ALL_EVENTS | JIM_DONT_WAIT);
recursion--;
}



+ 17
- 1
src/helper/command.h View File

@@ -39,6 +39,22 @@ enum command_mode {
COMMAND_ANY,
};

/**
* Helper struct to share a common Jim interpreter among multiple command
* contexts.
*/
struct command_interpreter {
/** Jim interpreter. */
Jim_Interp *interp;
/** Number of references held on this interpreter. */
unsigned int refcnt;
/**
* Determines whether the Jim interpreter should be free'd when the last
* reference is released.
*/
bool free;
};

struct command_context;

/** The type signature for command context's output handler. */
@@ -46,7 +62,7 @@ typedef int (*command_output_handler_t)(struct command_context *context,
const char *line);

struct command_context {
Jim_Interp *interp;
struct command_interpreter *interp;
enum command_mode mode;
struct command *commands;
int current_target;


+ 4
- 1
src/jtag/core.c View File

@@ -1582,7 +1582,10 @@ int jtag_init(struct command_context *cmd_ctx)
if (retval != ERROR_OK)
return retval;

if (Jim_Eval_Named(cmd_ctx->interp, "jtag_init", __FILE__, __LINE__) != JIM_OK)
retval = Jim_Eval_Named(cmd_ctx->interp->interp, "jtag_init", __FILE__,
__LINE__);

if (retval != JIM_OK)
return ERROR_FAIL;

return ERROR_OK;


+ 14
- 1
src/server/server.c View File

@@ -67,10 +67,23 @@ static int add_connection(struct service *service, struct command_context *cmd_c
int flag = 1;

c = malloc(sizeof(struct connection));

if (!c) {
LOG_ERROR("Failed to allocate connection.");
return ERROR_FAIL;
}

c->cmd_ctx = copy_command_context(cmd_ctx);

if (!c->cmd_ctx) {
LOG_ERROR("Failed to copy command context.");
free(c);
return ERROR_FAIL;
}

c->fd = -1;
c->fd_out = -1;
memset(&c->sin, 0, sizeof(c->sin));
c->cmd_ctx = copy_command_context(cmd_ctx);
c->service = service;
c->input_pending = 0;
c->priv = NULL;


+ 3
- 1
src/server/tcl_server.c View File

@@ -173,7 +173,7 @@ static int tcl_new_connection(struct connection *connection)

static int tcl_input(struct connection *connection)
{
Jim_Interp *interp = (Jim_Interp *)connection->cmd_ctx->interp;
Jim_Interp *interp;
int retval;
int i;
ssize_t rlen;
@@ -184,6 +184,8 @@ static int tcl_input(struct connection *connection)
char *tc_line_new;
int tc_line_size_new;

interp = connection->cmd_ctx->interp->interp;

rlen = connection_read(connection, &in, sizeof(in));
if (rlen <= 0) {
if (rlen < 0)


+ 1
- 1
src/target/dsp563xx.c View File

@@ -1470,7 +1470,7 @@ static int dsp563xx_get_default_memory(void)
if (!global_cmd_ctx)
return MEM_P;

interp = global_cmd_ctx->interp;
interp = global_cmd_ctx->interp->interp;

if (!interp)
return MEM_P;


+ 5
- 4
src/target/target.c View File

@@ -651,13 +651,14 @@ static int target_process_reset(struct command_context *cmd_ctx, enum target_res
jtag_poll_set_enabled(false);

sprintf(buf, "ocd_process_reset %s", n->name);
retval = Jim_Eval(cmd_ctx->interp, buf);
retval = Jim_Eval(cmd_ctx->interp->interp, buf);

jtag_poll_set_enabled(save_poll);

if (retval != JIM_OK) {
Jim_MakeErrorMessage(cmd_ctx->interp);
command_print(NULL, "%s\n", Jim_GetString(Jim_GetResult(cmd_ctx->interp), NULL));
Jim_MakeErrorMessage(cmd_ctx->interp->interp);
command_print(NULL, "%s\n",
Jim_GetString(Jim_GetResult(cmd_ctx->interp->interp), NULL));
return ERROR_FAIL;
}

@@ -1293,7 +1294,7 @@ static int target_init(struct command_context *cmd_ctx)
return retval;

retval = target_register_timer_callback(&handle_target,
polling_interval, 1, cmd_ctx->interp);
polling_interval, 1, cmd_ctx->interp->interp);
if (ERROR_OK != retval)
return retval;



Loading…
Cancel
Save