Add a SIGINT handler to debuginfod-find so that ctrl-c during
a download causes clean up to occur instead of immediately killing
the process and possibly leaving temp files in the client cache.

This change requires setting the client progressfn unconditionally
instead of only when --verbose is given.  This in turn requires a small
change to a debuginfod-find testcase in run-debuginfod-artifact-running.sh
to account for output differences between the debuginfod-find progressfn
and the debuginfod_client default_progressfn which was previously used
when debuginfod-find lacked -v but had DEBUGINFOD_PROGRESS=1 set.

https://sourceware.org/bugzilla/show_bug.cgi?id=33163

Signed-off-by: Aaron Merey <ame...@redhat.com>
---
 debuginfod/debuginfod-find.c             | 30 ++++++++++++++++++++++--
 tests/run-debuginfod-artifact-running.sh |  4 ++--
 2 files changed, 30 insertions(+), 4 deletions(-)

diff --git a/debuginfod/debuginfod-find.c b/debuginfod/debuginfod-find.c
index deba9560..39de65c3 100644
--- a/debuginfod/debuginfod-find.c
+++ b/debuginfod/debuginfod-find.c
@@ -30,6 +30,7 @@
 #include <fcntl.h>
 #include <gelf.h>
 #include <libdwelf.h>
+#include <signal.h>
 #ifndef DUMMY_LIBDEBUGINFOD
 #include <json-c/json.h>
 #endif
@@ -66,10 +67,22 @@ static const struct argp_option options[] =
 /* debuginfod connection handle.  */
 static debuginfod_client *client;
 static int verbose;
+static volatile sig_atomic_t interrupted;
+
+static void
+handle_sigint(int signo __attribute__((__unused__)))
+{
+  interrupted = 1;
+}
 
 int progressfn(debuginfod_client *c __attribute__((__unused__)),
               long a, long b)
 {
+  if (interrupted)
+    return 1;
+  if (verbose < 1)
+    return 0;
+
   static bool first = true;
   static struct timespec last;
   struct timespec now;
@@ -103,7 +116,6 @@ static error_t parse_opt (int key, char *arg, struct 
argp_state *state)
   switch (key)
     {
     case 'v': verbose++;
-      debuginfod_set_progressfn (client, & progressfn);
       if (verbose > 1)
         debuginfod_set_verbose_fd (client, STDERR_FILENO);
       break;
@@ -133,6 +145,16 @@ main(int argc, char** argv)
       return 1;
     }
 
+  /* Set SIGINT handler and progressfn so that temp files can be cleaned
+     up when a download is cancelled.  */
+  struct sigaction sa;
+  sigemptyset (&sa.sa_mask);
+  sa.sa_flags = 0;
+  sa.sa_handler = handle_sigint;
+  sigaction (SIGINT, &sa, NULL);
+
+  debuginfod_set_progressfn (client, & progressfn);
+
   /* Exercise user data pointer, to support testing only. */
   debuginfod_set_user_data (client, (void *)"Progress");
 
@@ -291,7 +313,11 @@ main(int argc, char** argv)
 
   if (rc < 0)
     {
-      fprintf(stderr, "Server query failed: %s\n", strerror(-rc));
+      if (interrupted != 0)
+        fputs ("Server query cancelled\n", stderr);
+      else
+        fprintf(stderr, "Server query failed: %s\n", strerror(-rc));
+
       return 1;
     }
   else
diff --git a/tests/run-debuginfod-artifact-running.sh 
b/tests/run-debuginfod-artifact-running.sh
index df42957b..2d5d834d 100755
--- a/tests/run-debuginfod-artifact-running.sh
+++ b/tests/run-debuginfod-artifact-running.sh
@@ -105,10 +105,10 @@ cmp $filename F/prog2
 grep -q Progress vlog
 grep -q Downloaded.from vlog
 tempfiles vlog
-filename=`testrun env DEBUGINFOD_PROGRESS=1 
${abs_top_builddir}/debuginfod/debuginfod-find executable $BUILDID2 2>vlog2`
+filename=`testrun env DEBUGINFOD_PROGRESS=1 
${abs_top_builddir}/debuginfod/debuginfod-find -v executable $BUILDID2 2>vlog2`
 cmp $filename F/prog2
-grep -q 'Downloading.*http' vlog2
 tempfiles vlog2
+grep -q 'Progress' vlog2
 filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find source 
$BUILDID2 ${PWD}/prog2.c`
 cmp $filename ${PWD}/prog2.c
 
-- 
2.50.1

Reply via email to