diff --git a/alerts.c b/alerts.c index 708a24e2..6696369f 100644 --- a/alerts.c +++ b/alerts.c @@ -64,7 +64,7 @@ alerts_callback(__unused int fd, __unused short events, __unused void *arg) TAILQ_REMOVE(&alerts_list, w, alerts_entry); w->flags &= ~WINDOW_ALERTFLAGS; - window_remove_ref(w); + window_remove_ref(w, __func__); } alerts_fired = 0; } @@ -144,16 +144,18 @@ alerts_queue(struct window *w, int flags) log_debug("@%u alerts flags added %#x", w->id, flags); } - if (!w->alerts_queued) { - w->alerts_queued = 1; - TAILQ_INSERT_TAIL(&alerts_list, w, alerts_entry); - w->references++; - } + if (alerts_enabled(w, flags)) { + if (!w->alerts_queued) { + w->alerts_queued = 1; + TAILQ_INSERT_TAIL(&alerts_list, w, alerts_entry); + window_add_ref(w, __func__); + } - if (!alerts_fired && alerts_enabled(w, flags)) { - log_debug("alerts check queued (by @%u)", w->id); - event_once(-1, EV_TIMEOUT, alerts_callback, NULL, NULL); - alerts_fired = 1; + if (!alerts_fired) { + log_debug("alerts check queued (by @%u)", w->id); + event_once(-1, EV_TIMEOUT, alerts_callback, NULL, NULL); + alerts_fired = 1; + } } } diff --git a/notify.c b/notify.c index e16973ec..0241fa60 100644 --- a/notify.c +++ b/notify.c @@ -100,12 +100,12 @@ notify_callback(struct cmdq_item *item, void *data) if (ne->client != NULL) server_client_unref(ne->client); if (ne->session != NULL) - session_unref(ne->session); + session_remove_ref(ne->session, __func__); if (ne->window != NULL) - window_remove_ref(ne->window); + window_remove_ref(ne->window, __func__); if (ne->fs.s != NULL) - session_unref(ne->fs.s); + session_remove_ref(ne->fs.s, __func__); free((void *)ne->name); free(ne); @@ -135,13 +135,13 @@ notify_add(const char *name, struct cmd_find_state *fs, struct client *c, if (c != NULL) c->references++; if (s != NULL) - s->references++; + session_add_ref(s, __func__); if (w != NULL) - w->references++; + window_add_ref(w, __func__); cmd_find_copy_state(&ne->fs, fs); - if (ne->fs.s != NULL) - ne->fs.s->references++; /* cmd_find_valid_state need session */ + if (ne->fs.s != NULL) /* cmd_find_valid_state needs session */ + session_add_ref(ne->fs.s, __func__); new_item = cmdq_get_callback(notify_callback, ne); cmdq_append(NULL, new_item); diff --git a/session.c b/session.c index 238d531f..b52b0274 100644 --- a/session.c +++ b/session.c @@ -188,13 +188,21 @@ session_create(const char *prefix, const char *name, int argc, char **argv, return (s); } +/* Add a reference to a session. */ +void +session_add_ref(struct session *s, const char *from) +{ + s->references++; + log_debug("%s: %s %s, now %d", __func__, s->name, from, s->references); +} + /* Remove a reference from a session. */ void -session_unref(struct session *s) +session_remove_ref(struct session *s, const char *from) { - log_debug("session %s has %d references", s->name, s->references); - s->references--; + log_debug("%s: %s %s, now %d", __func__, s->name, from, s->references); + if (s->references == 0) event_once(-1, EV_TIMEOUT, session_free, s, NULL); } @@ -247,7 +255,7 @@ session_destroy(struct session *s) free((void *)s->cwd); - session_unref(s); + session_remove_ref(s, __func__); } /* Check a session name is valid: not empty and no colons or periods. */ diff --git a/tmux.h b/tmux.h index 3b39129a..453c3511 100644 --- a/tmux.h +++ b/tmux.h @@ -2116,7 +2116,8 @@ 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_right(struct window_pane *); void window_set_name(struct window *, const char *); -void window_remove_ref(struct window *); +void window_add_ref(struct window *, const char *); +void window_remove_ref(struct window *, const char *); void winlink_clear_flags(struct winlink *); int winlink_shuffle_up(struct session *, struct winlink *); @@ -2230,7 +2231,8 @@ struct session *session_create(const char *, const char *, int, char **, const char *, const char *, struct environ *, struct termios *, int, u_int, u_int, char **); void session_destroy(struct session *); -void session_unref(struct session *); +void session_add_ref(struct session *, const char *); +void session_remove_ref(struct session *, const char *); int session_check_name(const char *); void session_update_activity(struct session *, struct timeval *); struct session *session_next_session(struct session *); diff --git a/window-choose.c b/window-choose.c index b736c5b1..c3c5f921 100644 --- a/window-choose.c +++ b/window-choose.c @@ -225,10 +225,10 @@ static void window_choose_data_free(struct window_choose_data *wcd) { server_client_unref(wcd->start_client); - session_unref(wcd->start_session); + session_remove_ref(wcd->start_session, __func__); if (wcd->tree_session != NULL) - session_unref(wcd->tree_session); + session_remove_ref(wcd->tree_session, __func__); free(wcd->ft_template); format_free(wcd->ft); diff --git a/window.c b/window.c index 4aaee3a6..ed73050e 100644 --- a/window.c +++ b/window.c @@ -186,11 +186,11 @@ winlink_set_window(struct winlink *wl, struct window *w) { if (wl->window != NULL) { TAILQ_REMOVE(&wl->window->winlinks, wl, wentry); - window_remove_ref(w); + window_remove_ref(wl->window, __func__); } TAILQ_INSERT_TAIL(&w->winlinks, wl, wentry); wl->window = w; - w->references++; + window_add_ref(w, __func__); } void @@ -200,7 +200,7 @@ winlink_remove(struct winlinks *wwl, struct winlink *wl) if (w != NULL) { TAILQ_REMOVE(&w->winlinks, wl, wentry); - window_remove_ref(w); + window_remove_ref(w, __func__); } RB_REMOVE(winlinks, wwl, wl); @@ -361,8 +361,7 @@ window_create_spawn(const char *name, int argc, char **argv, const char *path, static void window_destroy(struct window *w) { - if (!TAILQ_EMPTY(&w->winlinks)) - fatalx("window destroyed with winlinks"); + log_debug("window @%u destroyed (%d references)", w->id, w->references); RB_REMOVE(windows, &windows, w); @@ -387,11 +386,18 @@ window_destroy(struct window *w) } void -window_remove_ref(struct window *w) +window_add_ref(struct window *w, const char *from) +{ + w->references++; + log_debug("%s: @%u %s, now %d", __func__, w->id, from, w->references); +} + +void +window_remove_ref(struct window *w, const char *from) { - if (w->references == 0) - fatal("bad reference count"); w->references--; + log_debug("%s: @%u %s, now %d", __func__, w->id, from, w->references); + if (w->references == 0) window_destroy(w); }