[Libguestfs] nbdkit 1.1.15 -- test-python failure

Richard W.M. Jones rjones at redhat.com
Thu Sep 28 09:45:38 UTC 2017


This seems to make the test more robust for me.

Rich.

-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
Fedora Windows cross-compiler. Compile Windows programs, test, and
build Windows installers. Over 100 libraries supported.
http://fedoraproject.org/wiki/MinGW
-------------- next part --------------
>From 63f0eb0889c8f8a82ba06a02a8a92d695902baad Mon Sep 17 00:00:00 2001
From: "Richard W.M. Jones" <rjones at redhat.com>
Date: Thu, 28 Sep 2017 10:41:38 +0100
Subject: [PATCH] Wait up to 5 seconds for running threads to complete before
 exiting.

There is a race condition where nbdkit exits (calling plugin_cleanup()
which unloads the plugin), while the plugin is in its plugin.close()
function in another thread.

This keeps track of the number of running threads and waits up to 5
seconds for the running threads to exit before exiting the main
program.

For further analysis, see also:
https://www.redhat.com/archives/libguestfs/2017-September/msg00226.html
---
 src/internal.h    |  3 +++
 src/main.c        | 13 +++++++++++++
 src/threadlocal.c | 35 +++++++++++++++++++++++++++++++++++
 3 files changed, 51 insertions(+)

diff --git a/src/internal.h b/src/internal.h
index 1fc5d69..b98be3d 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -182,6 +182,9 @@ extern size_t threadlocal_get_instance_num (void);
 extern void threadlocal_set_error (int err);
 extern int threadlocal_get_error (void);
 /*extern void threadlocal_get_sockaddr ();*/
+extern size_t get_running_threads (void);
+extern void incr_running_threads (void);
+extern void decr_running_threads (void);
 
 /* Declare program_name. */
 #if HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME == 1
diff --git a/src/main.c b/src/main.c
index c4e41e4..010a21a 100644
--- a/src/main.c
+++ b/src/main.c
@@ -184,6 +184,7 @@ main (int argc, char *argv[])
   int option_index;
   int help = 0, version = 0, dump_plugin = 0;
   int tls_set_on_cli = 0;
+  size_t count;
 
   threadlocal_init ();
 
@@ -486,6 +487,12 @@ main (int argc, char *argv[])
 
   start_serving ();
 
+  /* Wait, but not forever, for all threads to complete. */
+  debug ("waiting for running threads to complete");
+  for (count = 0; count < 5 && get_running_threads (); ++count)
+    sleep (1);
+  debug ("waited %zus for running threads to complete", count);
+
   plugin_cleanup ();
 
   free (unixsocket);
@@ -631,6 +638,12 @@ start_serving (void)
     threadlocal_new_server_thread ();
     if (handle_single_connection (0, 1) == -1)
       exit (EXIT_FAILURE);
+    /* When handling a single connection we reuse the main thread as
+     * the server thread.  We don't want to count it as a running
+     * thread, but it hasn't called pthread_exit(), so we need to
+     * explicitly decrement the running threads here.
+     */
+    decr_running_threads ();
     return;
   }
 
diff --git a/src/threadlocal.c b/src/threadlocal.c
index d6e3942..cc19d48 100644
--- a/src/threadlocal.c
+++ b/src/threadlocal.c
@@ -71,6 +71,8 @@ free_threadlocal (void *threadlocalv)
 
   free (threadlocal->addr);
   free (threadlocal);
+
+  decr_running_threads ();
 }
 
 void
@@ -91,6 +93,8 @@ threadlocal_new_server_thread (void)
 {
   struct threadlocal *threadlocal;
 
+  incr_running_threads ();
+
   threadlocal = calloc (1, sizeof *threadlocal);
   if (threadlocal == NULL) {
     perror ("malloc");
@@ -177,3 +181,34 @@ threadlocal_get_error (void)
   errno = err;
   return threadlocal ? threadlocal->err : 0;
 }
+
+/* These functions keep track of the number of running threads. */
+static pthread_mutex_t running_threads_lock = PTHREAD_MUTEX_INITIALIZER;
+static size_t running_threads = 0;
+
+size_t
+get_running_threads (void)
+{
+  size_t r;
+
+  pthread_mutex_lock (&running_threads_lock);
+  r = running_threads;
+  pthread_mutex_unlock (&running_threads_lock);
+  return r;
+}
+
+void
+incr_running_threads (void)
+{
+  pthread_mutex_lock (&running_threads_lock);
+  running_threads++;
+  pthread_mutex_unlock (&running_threads_lock);
+}
+
+void
+decr_running_threads (void)
+{
+  pthread_mutex_lock (&running_threads_lock);
+  running_threads--;
+  pthread_mutex_unlock (&running_threads_lock);
+}
-- 
2.13.2



More information about the Libguestfs mailing list