1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
From: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
Date: Tue, 1 Nov 2016 00:14:10 -0400
Subject: 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>
---
agent/call-scd.c | 2 ++
agent/gpg-agent.c | 29 +++++++++++++++++++++++++++--
2 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/agent/call-scd.c b/agent/call-scd.c
index c5b95f4..762de82 100644
--- a/agent/call-scd.c
+++ b/agent/call-scd.c
@@ -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);
diff --git a/agent/gpg-agent.c b/agent/gpg-agent.c
index 2882767..0801449 100644
--- a/agent/gpg-agent.c
+++ b/agent/gpg-agent.c
@@ -2374,6 +2374,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. */
@@ -2730,7 +2750,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;
}
@@ -2810,7 +2831,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;
}
@@ -3020,6 +3042,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);
|