summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRichard W.M. Jones <rjones@redhat.com>2012-02-15 16:54:05 +0000
committerRichard W.M. Jones <rjones@redhat.com>2012-02-15 16:59:18 +0000
commitafed7e493dcd594620f19b93e9fb73e58553f60a (patch)
tree370b8f8a2de14727f47e370d84d7f6e9b8f1343b /src
parentc9ea94810e2f7a5fcce2a7136eb07ce795f49c53 (diff)
downloadlibguestfs-afed7e493dcd594620f19b93e9fb73e58553f60a.tar.gz
libguestfs-afed7e493dcd594620f19b93e9fb73e58553f60a.tar.xz
libguestfs-afed7e493dcd594620f19b93e9fb73e58553f60a.zip
appliance: Make appliance building thread-safe (RHBZ#790721).
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.
Diffstat (limited to 'src')
-rw-r--r--src/launch.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/src/launch.c b/src/launch.c
index 4e2fba9d..124e7587 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);