Fix up window reference counting and don't crash if the rename timer

fires while the window is dead but still referenced. Fixes problem
reported by Michael Scholz.
This commit is contained in:
Nicholas Marriott 2012-08-21 10:00:33 +00:00
parent a1e4908ed7
commit 58e8e0eac8
4 changed files with 18 additions and 8 deletions

View File

@ -50,6 +50,9 @@ window_name_callback(unused int fd, unused short events, void *data)
struct window *w = data; struct window *w = data;
char *name, *wname; char *name, *wname;
if (w->active == NULL)
return;
if (!options_get_number(&w->options, "automatic-rename")) { if (!options_get_number(&w->options, "automatic-rename")) {
if (event_initialized(&w->name_timer)) if (event_initialized(&w->name_timer))
event_del(&w->name_timer); event_del(&w->name_timer);

View File

@ -125,7 +125,8 @@ notify_drain(void)
if (ne->session != NULL) if (ne->session != NULL)
ne->session->references--; ne->session->references--;
if (ne->window != NULL) if (ne->window != NULL)
ne->window->references--; window_remove_ref(ne->window);
TAILQ_REMOVE(&notify_queue, ne, entry); TAILQ_REMOVE(&notify_queue, ne, entry);
free(ne); free(ne);
} }

1
tmux.h
View File

@ -2130,6 +2130,7 @@ struct window_pane *window_pane_find_down(struct window_pane *);
struct window_pane *window_pane_find_left(struct window_pane *); struct window_pane *window_pane_find_left(struct window_pane *);
struct window_pane *window_pane_find_right(struct window_pane *); struct window_pane *window_pane_find_right(struct window_pane *);
void window_set_name(struct window *, const char *); void window_set_name(struct window *, const char *);
void window_remove_ref(struct window *);
void winlink_clear_flags(struct winlink *); void winlink_clear_flags(struct winlink *);
void window_mode_attrs(struct grid_cell *, struct options *); void window_mode_attrs(struct grid_cell *, struct options *);

View File

@ -182,13 +182,8 @@ winlink_remove(struct winlinks *wwl, struct winlink *wl)
free(wl->status_text); free(wl->status_text);
free(wl); free(wl);
if (w != NULL) { if (w != NULL)
if (w->references == 0) window_remove_ref(w);
fatal("bad reference count");
w->references--;
if (w->references == 0)
window_destroy(w);
}
} }
struct winlink * struct winlink *
@ -362,6 +357,16 @@ window_destroy(struct window *w)
free(w); free(w);
} }
void
window_remove_ref(struct window *w)
{
if (w->references == 0)
fatal("bad reference count");
w->references--;
if (w->references == 0)
window_destroy(w);
}
void void
window_set_name(struct window *w, const char *new_name) window_set_name(struct window *w, const char *new_name)
{ {