generator: Acquire lock to prevent two parallel runs of the generator.
authorRichard Jones <rjones@redhat.com>
Thu, 19 Nov 2009 13:48:59 +0000 (13:48 +0000)
committerRichard Jones <rjones@redhat.com>
Thu, 19 Nov 2009 14:03:59 +0000 (14:03 +0000)
This commit acquires a lock on a file to prevent two parallel runs of
the generator from stomping on each other.  The second run will wait
for the first to complete before starting.

The lock is acquired on the "HACKING" file because it's convenient --
we are already checking this file exists to make sure that we don't
start off in the wrong directory.

Tested by adding some artificial sleeps in the code to observe
locking behaviour between two parallel runs.

src/generator.ml [changed mode: 0644->0755]

old mode 100644 (file)
new mode 100755 (executable)
index c261ea2..e3584cc
@@ -10176,18 +10176,39 @@ let output_to filename =
   in
   close
 
+let perror msg = function
+  | Unix.Unix_error (err, _, _) ->
+      eprintf "%s: %s\n" msg (Unix.error_message err)
+  | exn ->
+      eprintf "%s: %s\n" msg (Printexc.to_string exn)
+
 (* Main program. *)
 let () =
-  check_functions ();
-
-  if not (Sys.file_exists "HACKING") then (
-    eprintf "\
+  let lock_fd =
+    try Unix.openfile "HACKING" [Unix.O_RDWR] 0
+    with
+    | Unix.Unix_error (Unix.ENOENT, _, _) ->
+       eprintf "\
 You are probably running this from the wrong directory.
 Run it from the top source directory using the command
   src/generator.ml
 ";
-    exit 1
-  );
+       exit 1
+    | exn ->
+       perror "open: HACKING" exn;
+       exit 1 in
+
+  (* Acquire a lock so parallel builds won't try to run the generator
+   * twice at the same time.  Subsequent builds will wait for the first
+   * one to finish.  Note the lock is released implicitly when the
+   * program exits.
+   *)
+  (try Unix.lockf lock_fd Unix.F_LOCK 1
+   with exn ->
+     perror "lock: HACKING" exn;
+     exit 1);
+
+  check_functions ();
 
   let close = output_to "src/guestfs_protocol.x" in
   generate_xdr ();