From: "Richard W.M. Jones" <rjones(a)redhat.com>
Appliance building can be called from multiple processes, but this is
only safe if each process holds a lock on the 'checksum' file.
However threads within a process are not excluded by a file lock, and
so this strategy completely failed for a multithreaded program calling
guestfs_launch in parallel.
Since it makes no sense for threads in a single program to race each
other to try to create the appliance, add a lock around appliance
building.
This serialises building the appliance, but the rest of guestfs_launch
(eg. starting up qemu) can run in parallel.
---
src/launch.c | 13 ++++++++++++-
1 files changed, 12 insertions(+), 1 deletions(-)
diff --git a/src/launch.c b/src/launch.c
index 4e2fba9..124e758 100644
--- a/src/launch.c
+++ b/src/launch.c
@@ -477,6 +477,13 @@ guestfs__launch (guestfs_h *g)
}
}
+/* RHBZ#790721: It makes no sense to have multiple threads racing to
+ * build the appliance from within a single process, and the code
+ * isn't safe for that anyway. Therefore put a thread lock around
+ * appliance building.
+ */
+gl_lock_define_initialized (static, building_lock);
+
static int
launch_appliance (guestfs_h *g)
{
@@ -501,8 +508,12 @@ launch_appliance (guestfs_h *g)
/* Locate and/or build the appliance. */
char *kernel = NULL, *initrd = NULL, *appliance = NULL;
- if (guestfs___build_appliance (g, &kernel, &initrd, &appliance) == -1)
+ gl_lock_lock (building_lock);
+ if (guestfs___build_appliance (g, &kernel, &initrd, &appliance) == -1) {
+ gl_lock_unlock (building_lock);
return -1;
+ }
+ gl_lock_unlock (building_lock);
TRACE0 (launch_build_appliance_end);
--
1.7.9