From 57cc4d45d52e0af562172ac4044f311e1bb00c64 Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 28 Aug 2015 13:01:03 +0000 Subject: [PATCH 1/5] Make session_update_activity more useful and use it in more places. --- cmd-attach-session.c | 4 ++-- cmd-new-session.c | 2 +- cmd-switch-client.c | 2 +- server-client.c | 10 +++++----- server-fn.c | 2 +- session.c | 21 +++++++++++++-------- tmux.h | 2 +- 7 files changed, 24 insertions(+), 19 deletions(-) diff --git a/cmd-attach-session.c b/cmd-attach-session.c index 9f357d6e..356bd4aa 100644 --- a/cmd-attach-session.c +++ b/cmd-attach-session.c @@ -135,7 +135,7 @@ cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag, c->session = s; status_timer_start(c); notify_attached_session_changed(c); - session_update_activity(s); + session_update_activity(s, NULL); server_redraw_client(c); s->curw->flags &= ~WINLINK_ALERTFLAGS; } else { @@ -180,7 +180,7 @@ cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag, c->session = s; status_timer_start(c); notify_attached_session_changed(c); - session_update_activity(s); + session_update_activity(s, NULL); server_redraw_client(c); s->curw->flags &= ~WINLINK_ALERTFLAGS; diff --git a/cmd-new-session.c b/cmd-new-session.c index 2125ee88..fa4f1553 100644 --- a/cmd-new-session.c +++ b/cmd-new-session.c @@ -277,7 +277,7 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq) c->session = s; status_timer_start(c); notify_attached_session_changed(c); - session_update_activity(s); + session_update_activity(s, NULL); server_redraw_client(c); } recalculate_sizes(); diff --git a/cmd-switch-client.c b/cmd-switch-client.c index 6a79c7b7..8bc8a3c5 100644 --- a/cmd-switch-client.c +++ b/cmd-switch-client.c @@ -128,7 +128,7 @@ cmd_switch_client_exec(struct cmd *self, struct cmd_q *cmdq) c->last_session = c->session; c->session = s; status_timer_start(c); - session_update_activity(s); + session_update_activity(s, NULL); recalculate_sizes(); server_check_unattached(); diff --git a/server-client.c b/server-client.c index 82cec36c..da24e222 100644 --- a/server-client.c +++ b/server-client.c @@ -561,9 +561,7 @@ server_client_handle_key(struct client *c, int key) /* Update the activity timer. */ if (gettimeofday(&c->activity_time, NULL) != 0) fatal("gettimeofday failed"); - memcpy(&s->last_activity_time, &s->activity_time, - sizeof s->last_activity_time); - memcpy(&s->activity_time, &c->activity_time, sizeof s->activity_time); + session_update_activity(s, &c->activity_time); /* Number keys jump to pane in identify mode. */ if (c->flags & CLIENT_IDENTIFY && key >= '0' && key <= '9') { @@ -981,6 +979,7 @@ server_client_msg_dispatch(struct client *c) struct msg_stdin_data stdindata; const char *data; ssize_t n, datalen; + struct session *s; if ((n = imsg_read(&c->ibuf)) == -1 || n == 0) return (-1); @@ -1064,11 +1063,12 @@ server_client_msg_dispatch(struct client *c) if (c->tty.fd == -1) /* exited in the meantime */ break; + s = c->session; if (gettimeofday(&c->activity_time, NULL) != 0) fatal("gettimeofday"); - if (c->session != NULL) - session_update_activity(c->session); + if (s != NULL) + session_update_activity(s, &c->activity_time); tty_start_tty(&c->tty); server_redraw_client(c); diff --git a/server-fn.c b/server-fn.c index 469dd82d..cddd762f 100644 --- a/server-fn.c +++ b/server-fn.c @@ -421,7 +421,7 @@ server_destroy_session(struct session *s) c->session = s_new; status_timer_start(c); notify_attached_session_changed(c); - session_update_activity(s_new); + session_update_activity(s_new, NULL); server_redraw_client(c); } } diff --git a/session.c b/session.c index 5061083a..7572ac21 100644 --- a/session.c +++ b/session.c @@ -112,10 +112,6 @@ session_create(const char *name, int argc, char **argv, const char *path, s->references = 1; s->flags = 0; - if (gettimeofday(&s->creation_time, NULL) != 0) - fatal("gettimeofday failed"); - session_update_activity(s); - s->cwd = dup(cwd); s->curw = NULL; @@ -133,6 +129,10 @@ session_create(const char *name, int argc, char **argv, const char *path, memcpy(s->tio, tio, sizeof *s->tio); } + if (gettimeofday(&s->creation_time, NULL) != 0) + fatal("gettimeofday failed"); + session_update_activity(s, &s->creation_time); + s->sx = sx; s->sy = sy; @@ -224,12 +224,17 @@ session_check_name(const char *name) return (*name != '\0' && name[strcspn(name, ":.")] == '\0'); } -/* Update session active time. */ +/* Update activity time. */ void -session_update_activity(struct session *s) +session_update_activity(struct session *s, struct timeval *from) { - if (gettimeofday(&s->activity_time, NULL) != 0) - fatal("gettimeofday"); + struct timeval *last = &s->last_activity_time; + + memcpy(last, &s->activity_time, sizeof *last); + if (from == NULL) + gettimeofday(&s->activity_time, NULL); + else + memcpy(&s->activity_time, from, sizeof s->activity_time); } /* Find the next usable session. */ diff --git a/tmux.h b/tmux.h index 9fae33bd..cc38dab8 100644 --- a/tmux.h +++ b/tmux.h @@ -2248,7 +2248,7 @@ struct session *session_create(const char *, int, char **, const char *, void session_destroy(struct session *); void session_unref(struct session *); int session_check_name(const char *); -void session_update_activity(struct session *); +void session_update_activity(struct session *, struct timeval *); struct session *session_next_session(struct session *); struct session *session_previous_session(struct session *); struct winlink *session_new(struct session *, const char *, int, char **, From f6a0f8730efab9c52eaccbb62b5b1d27e8be7949 Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 28 Aug 2015 13:12:20 +0000 Subject: [PATCH 2/5] Per-session timers for locking, and remove the global one-second timer. --- cmd-set-option.c | 2 +- server.c | 45 ++------------------------------------------- session.c | 40 +++++++++++++++++++++++++++++++++++++++- tmux.h | 2 ++ 4 files changed, 44 insertions(+), 45 deletions(-) diff --git a/cmd-set-option.c b/cmd-set-option.c index 260961cb..56ca91e0 100644 --- a/cmd-set-option.c +++ b/cmd-set-option.c @@ -176,7 +176,7 @@ cmd_set_option_exec(struct cmd *self, struct cmd_q *cmdq) return (CMD_RETURN_ERROR); } - /* Start or stop timers when name or status options changed. */ + /* Start or stop timers if necessary. */ if (strcmp(oe->name, "automatic-rename") == 0) { RB_FOREACH(w, windows, &windows) { if (options_get_number(&w->options, "automatic-rename")) diff --git a/server.c b/server.c index f9b0dc52..0e7733c8 100644 --- a/server.c +++ b/server.c @@ -46,7 +46,6 @@ struct clients clients; int server_fd; int server_shutdown; struct event server_ev_accept; -struct event server_ev_second; struct session *marked_session; struct winlink *marked_winlink; @@ -163,9 +162,8 @@ server_create_socket(void) int server_start(int lockfd, char *lockfile) { - int pair[2]; - struct timeval tv; - char *cause; + int pair[2]; + char *cause; /* The first client is special and gets a socketpair; create it. */ if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0) @@ -243,11 +241,6 @@ server_start(int lockfd, char *lockfile) server_add_accept(0); - memset(&tv, 0, sizeof tv); - tv.tv_sec = 1; - evtimer_set(&server_ev_second, server_second_callback, NULL); - evtimer_add(&server_ev_second, &tv); - set_signals(server_signal_callback); server_loop(); status_prompt_save_history(); @@ -498,37 +491,3 @@ server_child_stopped(pid_t pid, int status) } } } - -/* Handle once-per-second timer events. */ -void -server_second_callback(unused int fd, unused short events, unused void *arg) -{ - struct timeval tv; - - server_lock_sessions(); - - evtimer_del(&server_ev_second); - memset(&tv, 0, sizeof tv); - tv.tv_sec = 1; - evtimer_add(&server_ev_second, &tv); -} - -/* Lock any sessions which have timed out. */ -void -server_lock_sessions(void) -{ - struct session *s; - int timeout; - time_t t; - - t = time(NULL); - RB_FOREACH(s, sessions, &sessions) { - if (s->flags & SESSION_UNATTACHED) - continue; - timeout = options_get_number(&s->options, "lock-after-time"); - if (timeout > 0 && t > s->activity_time.tv_sec + timeout) { - server_lock_session(s); - recalculate_sizes(); - } - } -} diff --git a/session.c b/session.c index 7572ac21..041adf2d 100644 --- a/session.c +++ b/session.c @@ -33,6 +33,8 @@ struct session_groups session_groups; void session_free(int, short, void *); +void session_lock_timer(int, short, void *); + struct winlink *session_next_alert(struct winlink *); struct winlink *session_previous_alert(struct winlink *); @@ -108,7 +110,7 @@ session_create(const char *name, int argc, char **argv, const char *path, struct session *s; struct winlink *wl; - s = xmalloc(sizeof *s); + s = xcalloc(1, sizeof *s); s->references = 1; s->flags = 0; @@ -149,6 +151,10 @@ session_create(const char *name, int argc, char **argv, const char *path, } RB_INSERT(sessions, &sessions, s); + if (gettimeofday(&s->creation_time, NULL) != 0) + fatal("gettimeofday failed"); + session_update_activity(s, &s->creation_time); + if (argc >= 0) { wl = session_new(s, NULL, argc, argv, path, cwd, idx, cause); if (wl == NULL) { @@ -200,6 +206,9 @@ session_destroy(struct session *s) free(s->tio); + if (event_initialized(&s->lock_timer)) + event_del(&s->lock_timer); + session_group_remove(s); environ_free(&s->environ); options_free(&s->options); @@ -224,17 +233,46 @@ session_check_name(const char *name) return (*name != '\0' && name[strcspn(name, ":.")] == '\0'); } +/* Lock session if it has timed out. */ +void +session_lock_timer(unused int fd, unused short events, void *arg) +{ + struct session *s = arg; + + if (s->flags & SESSION_UNATTACHED) + return; + + log_debug("session %s locked, activity time %lld", s->name, + (long long)s->activity_time.tv_sec); + + server_lock_session(s); + recalculate_sizes(); +} + /* Update activity time. */ void session_update_activity(struct session *s, struct timeval *from) { struct timeval *last = &s->last_activity_time; + struct timeval tv; memcpy(last, &s->activity_time, sizeof *last); if (from == NULL) gettimeofday(&s->activity_time, NULL); else memcpy(&s->activity_time, from, sizeof s->activity_time); + + if (evtimer_initialized(&s->lock_timer)) + evtimer_del(&s->lock_timer); + else + evtimer_set(&s->lock_timer, session_lock_timer, s); + + if (~s->flags & SESSION_UNATTACHED) { + timerclear(&tv); + tv.tv_sec = options_get_number(&s->options, "lock-after-time"); + if (tv.tv_sec != 0) + evtimer_add(&s->lock_timer, &tv); + } } /* Find the next usable session. */ diff --git a/tmux.h b/tmux.h index cc38dab8..6ac0b578 100644 --- a/tmux.h +++ b/tmux.h @@ -993,6 +993,8 @@ struct session { struct timeval activity_time; struct timeval last_activity_time; + struct event lock_timer; + u_int sx; u_int sy; From ed2a486f46010559926f49b2f95fc3ceb61fe105 Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 28 Aug 2015 13:16:03 +0000 Subject: [PATCH 3/5] Don't leak name when freeing session, from Kuang-che Wu. --- session.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/session.c b/session.c index 041adf2d..c4e64e27 100644 --- a/session.c +++ b/session.c @@ -189,8 +189,10 @@ session_free(unused int fd, unused short events, void *arg) log_debug("sesson %s freed (%d references)", s->name, s->references); - if (s->references == 0) + if (s->references == 0) { + free(s->name); free(s); + } } /* Destroy a session. */ From f957db81d9c1c17468e57729f32aa67ffd3e23e0 Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 28 Aug 2015 13:21:25 +0000 Subject: [PATCH 4/5] Remove unused prototypes. --- server.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/server.c b/server.c index 0e7733c8..d36dda12 100644 --- a/server.c +++ b/server.c @@ -62,8 +62,6 @@ void server_signal_callback(int, short, void *); void server_child_signal(void); void server_child_exited(pid_t, int); void server_child_stopped(pid_t, int); -void server_second_callback(int, short, void *); -void server_lock_sessions(void); /* Set marked pane. */ void From b0940bdf5460ec3324254b5df68b5386513641b2 Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 28 Aug 2015 13:26:41 +0000 Subject: [PATCH 5/5] Check changed flag after restarting timer. --- names.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/names.c b/names.c index 0a3af903..aa0673ea 100644 --- a/names.c +++ b/names.c @@ -50,10 +50,6 @@ window_name_callback(unused int fd, unused short events, void *data) if (w->active == NULL) return; - if (~w->active->flags & PANE_CHANGED) - return; - w->active->flags &= ~PANE_CHANGED; - if (!options_get_number(&w->options, "automatic-rename")) { if (event_initialized(&w->name_timer)) event_del(&w->name_timer); @@ -61,6 +57,10 @@ window_name_callback(unused int fd, unused short events, void *data) } queue_window_name(w); + if (~w->active->flags & PANE_CHANGED) + return; + w->active->flags &= ~PANE_CHANGED; + name = format_window_name(w); if (strcmp(name, w->name) != 0) { window_set_name(w, name);