[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