Skip to content

Commit

Permalink
source-file and some other commands can recurse back into cmdq_continue,
Browse files Browse the repository at this point in the history
which could potentially free the currently running command, so we need
to take a reference to it in cmdq_continue_one.

Fixes problem reported by Theo Buehler.
  • Loading branch information
nicm committed Oct 14, 2016
1 parent 0ec18e5 commit 1721d19
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 6 deletions.
5 changes: 4 additions & 1 deletion cfg.c
Expand Up @@ -129,7 +129,10 @@ load_cfg(const char *path, struct cmd_q *cmdq, int quiet)
static void
cfg_default_done(__unused struct cmd_q *cmdq)
{
if (--cfg_references != 0)
log_debug("%s: %u references%s", __func__, cfg_references,
cfg_finished ? " (finished)" : "");

if (cfg_finished || --cfg_references != 0)
return;
cfg_finished = 1;

Expand Down
11 changes: 9 additions & 2 deletions cmd-queue.c
Expand Up @@ -55,6 +55,8 @@ cmdq_new(struct client *c)
int
cmdq_free(struct cmd_q *cmdq)
{
log_debug("cmdq %p free: %u references", cmdq, cmdq->references);

if (--cmdq->references != 0) {
if (cmdq->flags & CMD_Q_DEAD)
return (1);
Expand Down Expand Up @@ -186,13 +188,16 @@ cmdq_append(struct cmd_q *cmdq, struct cmd_list *cmdlist, struct mouse_event *m)
static enum cmd_retval
cmdq_continue_one(struct cmd_q *cmdq)
{
struct cmd_list *cmdlist = cmdq->item->cmdlist;
struct cmd *cmd = cmdq->cmd;
enum cmd_retval retval;
char *tmp;
int flags = !!(cmd->flags & CMD_CONTROL);
const char *name;
struct cmd_find_state *fsp, fs;

cmdlist->references++;

tmp = cmd_print(cmd);
log_debug("cmdq %p: %s", cmdq, tmp);
free(tmp);
Expand Down Expand Up @@ -225,10 +230,12 @@ cmdq_continue_one(struct cmd_q *cmdq)

end:
cmdq_guard(cmdq, "end", flags);
cmd_list_free(cmdlist);
return (retval);

error:
cmdq_guard(cmdq, "error", flags);
cmd_list_free(cmdlist);
return (CMD_RETURN_ERROR);
}

Expand All @@ -244,8 +251,7 @@ cmdq_continue(struct cmd_q *cmdq)
cmdq->references++;
notify_disable();

log_debug("continuing cmdq %p: flags %#x, client %p", cmdq, cmdq->flags,
c);
log_debug("continuing cmdq %p: flags %#x (%p)", cmdq, cmdq->flags, c);

empty = TAILQ_EMPTY(&cmdq->queue);
if (empty)
Expand Down Expand Up @@ -282,6 +288,7 @@ cmdq_continue(struct cmd_q *cmdq)
} while (cmdq->item != NULL);

empty:
log_debug("cmdq %p empty", cmdq);
if (cmdq->client_exit > 0)
cmdq->client->flags |= CLIENT_EXIT;
if (cmdq->emptyfn != NULL)
Expand Down
7 changes: 4 additions & 3 deletions cmd-source-file.c
Expand Up @@ -68,6 +68,8 @@ cmd_source_file_exec(struct cmd *self, struct cmd_q *cmdq)
return (CMD_RETURN_NORMAL);
}

log_debug("%s: cmdq %p, parent %p", __func__, cmdq1, cmdq);

cmdq->references++;
cfg_references++;

Expand All @@ -80,16 +82,15 @@ cmd_source_file_done(struct cmd_q *cmdq1)
{
struct cmd_q *cmdq = cmdq1->data;

log_debug("%s: cmdq %p, parent %p", __func__, cmdq1, cmdq);

if (cmdq1->client_exit >= 0)
cmdq->client_exit = cmdq1->client_exit;

cmdq_free(cmdq1);

cfg_references--;

if (cmdq_free(cmdq))
return;

if (cfg_references == 0)
cfg_print_causes(cmdq);
cmdq_continue(cmdq);
Expand Down

0 comments on commit 1721d19

Please sign in to comment.