summaryrefslogtreecommitdiffstats
path: root/cmd-queue.c
diff options
context:
space:
mode:
authornicm <nicm>2016-10-14 18:41:53 +0000
committernicm <nicm>2016-10-14 18:41:53 +0000
commit1721d1994eb03beb8217fa3e61ed0cc097dd899e (patch)
tree43e7b2ac7cfbfee0b83cb80f59133d9ee9e65f0f /cmd-queue.c
parent0ec18e537d7f67732a789c0984bc1cb89dbb0adf (diff)
source-file and some other commands can recurse back into cmdq_continue,
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.
Diffstat (limited to 'cmd-queue.c')
-rw-r--r--cmd-queue.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/cmd-queue.c b/cmd-queue.c
index 8b28dd65..bafff1d6 100644
--- a/cmd-queue.c
+++ b/cmd-queue.c
@@ -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);
@@ -186,6 +188,7 @@ 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;
@@ -193,6 +196,8 @@ cmdq_continue_one(struct cmd_q *cmdq)
const char *name;
struct cmd_find_state *fsp, fs;
+ cmdlist->references++;
+
tmp = cmd_print(cmd);
log_debug("cmdq %p: %s", cmdq, tmp);
free(tmp);
@@ -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);
}
@@ -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)
@@ -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)