agent: Avoid tight timer tick when possible.

* agent/gpg-agent.c (need_tick): Evaluate whether the short-phase
handle_tick() is needed.
(handle_connections): On each cycle of the select loop, adjust whether
we should call handle_tick() or not.
(start_connection_thread_ssh, do_start_connection_thread): Signal the
main loop when the child terminates.
* agent/call-scd.c (start_scd): Call interrupt_main_thread_loop() once
the scdaemon thread context has started up.

--

With this change, an idle gpg-agent that has no scdaemon running only
wakes up once a minute (to check_own_socket).

Thanks to Ian Jackson and NIIBE Yutaka who helped me improve some of
the blocking and corner cases.

Signed-off-by: Daniel Kahn Gillmor <dkg@fifthhorseman.net>

Gbp-Pq: Topic gpg-agent-idling
Gbp-Pq: Name agent-Avoid-tight-timer-tick-when-possible.patch
This commit is contained in:
Daniel Kahn Gillmor 2016-11-01 00:14:10 -04:00 committed by openKylinBot
parent 3d2a404247
commit 6ce0d1ee52
2 changed files with 29 additions and 2 deletions

View File

@ -414,6 +414,8 @@ start_scd (ctrl_t ctrl)
primary_scd_ctx = ctx;
primary_scd_ctx_reusable = 0;
/* notify the main loop that something has changed */
interrupt_main_thread_loop ();
leave:
xfree (abs_homedir);

View File

@ -2376,6 +2376,26 @@ create_directories (void)
}
static int
need_tick (void)
{
#ifdef HAVE_W32_SYSTEM
/* We do not know how to interrupt the select loop on Windows, so we
always need a short tick there. */
return 1;
#else
/* if we were invoked like "gpg-agent cmd arg1 arg2" then we need to
watch our parent. */
if (parent_pid != (pid_t)(-1))
return 1;
/* if scdaemon is running, we need to check that it's alive */
if (agent_scd_check_running ())
return 1;
/* otherwise, nothing fine-grained to do. */
return 0;
#endif /*HAVE_W32_SYSTEM*/
}
/* This is the worker for the ticker. It is called every few seconds
and may only do fast operations. */
@ -2732,7 +2752,8 @@ do_start_connection_thread (ctrl_t ctrl)
agent_deinit_default_ctrl (ctrl);
xfree (ctrl);
active_connections--;
if (--active_connections == 0)
interrupt_main_thread_loop();
return NULL;
}
@ -2812,7 +2833,8 @@ start_connection_thread_ssh (void *arg)
agent_deinit_default_ctrl (ctrl);
xfree (ctrl);
active_connections--;
if (--active_connections == 0)
interrupt_main_thread_loop();
return NULL;
}
@ -3022,6 +3044,9 @@ handle_connections (gnupg_fd_t listen_fd,
thus a simple assignment is fine to copy the entire set. */
read_fdset = fdset;
/* avoid a fine-grained timer if we don't need one: */
timertbl[0].interval.tv_sec = need_tick () ? TIMERTICK_INTERVAL : 0;
/* loop through all timers, fire any registered functions, and
plan next timer to trigger */
npth_clock_gettime (&curtime);