agent: Avoid tight timer tick when possible.
authorDaniel Kahn Gillmor <dkg@fifthhorseman.net>
Tue, 1 Nov 2016 04:14:10 +0000 (00:14 -0400)
committerDaniel Kahn Gillmor <dkg@fifthhorseman.net>
Thu, 30 Aug 2018 15:57:15 +0000 (16:57 +0100)
* 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

agent/call-scd.c
agent/gpg-agent.c

index 16139fdc9a74fe73591e60ee17408c9312bc37fd..bf7732bf06a48f4fc1185c3e92e084b7fd8c7c60 100644 (file)
@@ -415,6 +415,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);
index 88f18055c48e2f461afdd59e3646fdd9835829f1..92b3d0b1f38eaf2d1ca99dd389c6c72e10b0f7d4 100644 (file)
@@ -2369,6 +2369,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. */
@@ -2722,7 +2742,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;
 }
 
@@ -2802,7 +2823,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;
 }
 
@@ -3012,6 +3034,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);