diff options
author | Richard W.M. Jones <rjones@redhat.com> | 2012-02-15 16:54:05 +0000 |
---|---|---|
committer | Richard W.M. Jones <rjones@redhat.com> | 2012-02-15 16:59:18 +0000 |
commit | afed7e493dcd594620f19b93e9fb73e58553f60a (patch) | |
tree | 370b8f8a2de14727f47e370d84d7f6e9b8f1343b /src | |
parent | c9ea94810e2f7a5fcce2a7136eb07ce795f49c53 (diff) | |
download | libguestfs-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.c | 13 |
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); |