aboutsummaryrefslogtreecommitdiffstats
path: root/common/asshelp.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/asshelp.c')
-rw-r--r--common/asshelp.c63
1 files changed, 53 insertions, 10 deletions
diff --git a/common/asshelp.c b/common/asshelp.c
index b2d13f32b..615bb8d3b 100644
--- a/common/asshelp.c
+++ b/common/asshelp.c
@@ -231,25 +231,68 @@ start_new_gpg_agent (assuan_context_t *r_ctx,
and thus there is no need for the GPG_AGENT_INFO
envvar. This is possible as we don't have a real unix
domain socket but use a plain file and thus there is no
- need to care about non-local file systems. */
+ need to care about non-local file systems. We use a
+ named mutex to interlock the spawning. There is just
+ one problem with that: If gpg-agent needs more than 3
+ seconds to come up and listen on the socket we might
+ still spawn another agent. However this is no serious
+ problem because an agent detects this and handles it.
+ Thus the mutex merely helps to save resources in the
+ most common cases. */
const char *argv[3];
+ HANDLE mutex;
+ int waitrc;
argv[0] = "--daemon";
argv[1] = "--use-standard-socket";
argv[2] = NULL;
- rc = gnupg_spawn_process_detached (agent_program, argv, NULL);
- if (rc)
- log_debug ("failed to start agent `%s': %s\n",
- agent_program, gpg_strerror (rc));
+ mutex = CreateMutex (NULL, FALSE, "GnuPG_spawn_agent_sentinel");
+ if (!mutex)
+ {
+ log_error ("failed to create the spawn_agent mutex: %s\n",
+ w32_strerror (-1));
+ rc = gpg_error (GPG_ERR_GENERAL);
+ }
+ else if ((waitrc = WaitForSingleObject (mutex, 5000))
+ == WAIT_OBJECT_0)
+ {
+ rc = assuan_socket_connect (&ctx, sockname, 0);
+ if (rc)
+ {
+ /* Still not available. */
+ rc = gnupg_spawn_process_detached (agent_program,
+ argv, NULL);
+ if (rc)
+ log_debug ("failed to start agent `%s': %s\n",
+ agent_program, gpg_strerror (rc));
+ else
+ {
+ /* Give the agent some time to prepare itself. */
+ gnupg_sleep (3);
+ /* Now try again to connect the agent. */
+ rc = assuan_socket_connect (&ctx, sockname, 0);
+ }
+ }
+ if (!ReleaseMutex (mutex))
+ log_error ("failed to release the spawn_agent mutex: %s\n",
+ w32_strerror (-1));
+ }
+ else if (waitrc == WAIT_TIMEOUT)
+ {
+ log_info ("error waiting for the spawn_agent mutex: timeout\n");
+ rc = gpg_error (GPG_ERR_GENERAL);
+ }
else
{
- /* Give the agent some time to prepare itself. */
- gnupg_sleep (3);
- /* Now try again to connect the agent. */
- rc = assuan_socket_connect (ctx, sockname, 0, 0);
+ log_debug ("error waiting for the spawn_agent mutex: "
+ "(code=%d) %s\n", waitrc, w32_strerror (-1));
+ rc = gpg_error (GPG_ERR_GENERAL);
}
- }
+
+ if (mutex)
+ CloseHandle (mutex);
+ }
#else /*!HAVE_W32_SYSTEM*/
{
const char *pgmname;