From 0471ff9d3bf8d6b9a359f3c426d70d0935066907 Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Wed, 8 Nov 2017 16:15:30 +0100 Subject: [PATCH 1/2] assuan: Reorganize waiting for socket. * common/asshelp.c (wait_for_sock): New function, collecting codepaths from... (start_new_gpg_agent) here and... (start_new_dirmngr) here. -- This has no functional change, but makes it easier to make this function more efficient. GnuPG-bug-id: 3490 Signed-off-by: Daniel Kahn Gillmor --- common/asshelp.c | 72 ++++++++++++++++++++---------------------------- 1 file changed, 30 insertions(+), 42 deletions(-) diff --git a/common/asshelp.c b/common/asshelp.c index f3a92f9e5..68a41be7e 100644 --- a/common/asshelp.c +++ b/common/asshelp.c @@ -307,6 +307,32 @@ unlock_spawning (lock_spawn_t *lock, const char *name) } } +static gpg_error_t +wait_for_sock (int secs, const char *name, const char *sockname, int verbose, assuan_context_t ctx, int *did_success_msg) +{ + int i; + gpg_error_t err = 0; + for (i=0; i < secs; i++) + { + if (verbose) + log_info (_("waiting for the %s to come up ... (%ds)\n"), + name, secs - i); + gnupg_sleep (1); + err = assuan_socket_connect (ctx, sockname, 0, 0); + if (!err) + { + if (verbose) + { + log_info (_("connection to %s established\n"), + name); + *did_success_msg = 1; + } + break; + } + } + return err; +} + /* Try to connect to the agent via socket or start it if it is not running and AUTOSTART is set. Handle the server's initial greeting. Returns a new assuan context at R_CTX or an error @@ -433,25 +459,8 @@ start_new_gpg_agent (assuan_context_t *r_ctx, log_error ("failed to start agent '%s': %s\n", agent_program, gpg_strerror (err)); else - { - for (i=0; i < SECS_TO_WAIT_FOR_AGENT; i++) - { - if (verbose) - log_info (_("waiting for the agent to come up ... (%ds)\n"), - SECS_TO_WAIT_FOR_AGENT - i); - gnupg_sleep (1); - err = assuan_socket_connect (ctx, sockname, 0, 0); - if (!err) - { - if (verbose) - { - log_info (_("connection to agent established\n")); - did_success_msg = 1; - } - break; - } - } - } + err = wait_for_sock (SECS_TO_WAIT_FOR_AGENT, "agent", + sockname, verbose, ctx, &did_success_msg); } unlock_spawning (&lock, "agent"); @@ -584,29 +593,8 @@ start_new_dirmngr (assuan_context_t *r_ctx, log_error ("failed to start the dirmngr '%s': %s\n", dirmngr_program, gpg_strerror (err)); else - { - int i; - - for (i=0; i < SECS_TO_WAIT_FOR_DIRMNGR; i++) - { - if (verbose) - log_info (_("waiting for the dirmngr " - "to come up ... (%ds)\n"), - SECS_TO_WAIT_FOR_DIRMNGR - i); - gnupg_sleep (1); - err = assuan_socket_connect (ctx, sockname, 0, 0); - if (!err) - { - if (verbose) - { - log_info (_("connection to the dirmngr" - " established\n")); - did_success_msg = 1; - } - break; - } - } - } + err = wait_for_sock (SECS_TO_WAIT_FOR_DIRMNGR, "dirmngr", + sockname, verbose, ctx, &did_success_msg); } unlock_spawning (&lock, "dirmngr"); From 149041b0b917f4298239fe18b5ebd5ead71584a6 Mon Sep 17 00:00:00 2001 From: Daniel Kahn Gillmor Date: Wed, 8 Nov 2017 16:26:40 +0100 Subject: [PATCH 2/2] assuan: Use exponential decay for first 1s of spinlock. * common/asshelp.c (wait_for_sock): instead of checking the socket every second, we check 10 times in the first second (with exponential decay). -- This cuts the wall clock time for the standard test suite roughly by half. GnuPG-bug-id: 3490 Signed-off-by: Daniel Kahn Gillmor --- common/asshelp.c | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/common/asshelp.c b/common/asshelp.c index 68a41be7e..76f812d8c 100644 --- a/common/asshelp.c +++ b/common/asshelp.c @@ -310,14 +310,32 @@ unlock_spawning (lock_spawn_t *lock, const char *name) static gpg_error_t wait_for_sock (int secs, const char *name, const char *sockname, int verbose, assuan_context_t ctx, int *did_success_msg) { - int i; gpg_error_t err = 0; - for (i=0; i < secs; i++) + int target_us = secs * 1000000; + int elapsed_us = 0; + /* + * 977us * 1024 = just a little more than 1s. + * so we will double this timeout 10 times in the first + * second, and then switch over to 1s checkins. + */ + int next_sleep_us = 977; + int lastalert = secs+1; + int secsleft; + + while (elapsed_us < target_us) { if (verbose) - log_info (_("waiting for the %s to come up ... (%ds)\n"), - name, secs - i); - gnupg_sleep (1); + { + secsleft = (target_us - elapsed_us)/1000000; + if (secsleft < lastalert) + { + log_info (_("waiting for the %s to come up ... (%ds)\n"), + name, secsleft); + lastalert = secsleft; + } + } + gnupg_usleep (next_sleep_us); + elapsed_us += next_sleep_us; err = assuan_socket_connect (ctx, sockname, 0, 0); if (!err) { @@ -329,6 +347,9 @@ wait_for_sock (int secs, const char *name, const char *sockname, int verbose, as } break; } + next_sleep_us *= 2; + if (next_sleep_us > 1000000) + next_sleep_us = 1000000; } return err; }