summaryrefslogtreecommitdiff
path: root/usr.bin/tmux
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@cvs.openbsd.org>2016-10-14 18:41:54 +0000
committerNicholas Marriott <nicm@cvs.openbsd.org>2016-10-14 18:41:54 +0000
commit1f9195d8cf739e4124db4512200c8278bbda6957 (patch)
tree60eeed8298c3a96df1710a8e3faf3bbdddbf3df0 /usr.bin/tmux
parentfc344322183bb75d15302a2e4a01e50b291ec829 (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 'usr.bin/tmux')
-rw-r--r--usr.bin/tmux/cfg.c7
-rw-r--r--usr.bin/tmux/cmd-queue.c13
-rw-r--r--usr.bin/tmux/cmd-source-file.c9
3 files changed, 20 insertions, 9 deletions
diff --git a/usr.bin/tmux/cfg.c b/usr.bin/tmux/cfg.c
index 4ccbf6d4d5e..86dd159ea67 100644
--- a/usr.bin/tmux/cfg.c
+++ b/usr.bin/tmux/cfg.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cfg.c,v 1.47 2016/10/11 13:45:47 nicm Exp $ */
+/* $OpenBSD: cfg.c,v 1.48 2016/10/14 18:41:53 nicm Exp $ */
/*
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -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;
diff --git a/usr.bin/tmux/cmd-queue.c b/usr.bin/tmux/cmd-queue.c
index aefc1a3ddd5..1c5e08dfffb 100644
--- a/usr.bin/tmux/cmd-queue.c
+++ b/usr.bin/tmux/cmd-queue.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-queue.c,v 1.40 2016/10/13 22:48:51 nicm Exp $ */
+/* $OpenBSD: cmd-queue.c,v 1.41 2016/10/14 18:41:53 nicm Exp $ */
/*
* Copyright (c) 2013 Nicholas Marriott <nicholas.marriott@gmail.com>
@@ -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)
diff --git a/usr.bin/tmux/cmd-source-file.c b/usr.bin/tmux/cmd-source-file.c
index ec95314f2aa..5f00d8273b9 100644
--- a/usr.bin/tmux/cmd-source-file.c
+++ b/usr.bin/tmux/cmd-source-file.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmd-source-file.c,v 1.27 2016/10/13 22:48:51 nicm Exp $ */
+/* $OpenBSD: cmd-source-file.c,v 1.28 2016/10/14 18:41:53 nicm Exp $ */
/*
* Copyright (c) 2008 Tiago Cunha <me@tiagocunha.org>
@@ -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++;
@@ -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);