aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--configure.ml8
-rw-r--r--lib/spawn.ml8
-rw-r--r--lib/system.ml58
-rw-r--r--plugins/micromega/mutils.ml8
4 files changed, 55 insertions, 27 deletions
diff --git a/configure.ml b/configure.ml
index f72910d4c..e64c04254 100644
--- a/configure.ml
+++ b/configure.ml
@@ -38,6 +38,12 @@ let check_exit_code (_,code) = match code with
| Unix.WSIGNALED n -> failwith ("killed by signal " ^ i2s n)
| Unix.WSTOPPED n -> failwith ("stopped by signal " ^ i2s n)
+(** As for Unix.close_process, our Unix.waipid will ignore all EINTR *)
+
+let rec waitpid_non_intr pid =
+ try Unix.waitpid [] pid
+ with Unix.Unix_error (Unix.EINTR, _, _) -> waitpid_non_intr pid
+
(** Below, we'd better read all lines on a channel before closing it,
otherwise a SIGPIPE could be encountered by the sub-process *)
@@ -76,7 +82,7 @@ let run ?(fatal=true) ?(err=StdErr) prog args =
let () = Unix.close nul_w in
let line = read_first_line_and_close out_r in
let _ = read_first_line_and_close nul_r in
- let () = check_exit_code (Unix.waitpid [] pid) in
+ let () = check_exit_code (waitpid_non_intr pid) in
line
with
| _ when not fatal && not !verbose -> ""
diff --git a/lib/spawn.ml b/lib/spawn.ml
index e350926b7..f32aa4d62 100644
--- a/lib/spawn.ml
+++ b/lib/spawn.ml
@@ -221,9 +221,11 @@ let kill_if p ~sec test =
false
end else true)
-let wait { pid = (unixpid, _) } =
- try snd (Unix.waitpid [] unixpid)
- with Unix.Unix_error _ -> Unix.WEXITED 0o400
+let rec wait p =
+ try snd (Unix.waitpid [] (fst p.pid))
+ with
+ | Unix.Unix_error (Unix.EINTR, _, _) -> wait p
+ | Unix.Unix_error _ -> Unix.WEXITED 0o400
end
diff --git a/lib/system.ml b/lib/system.ml
index aa6671116..6c357ee36 100644
--- a/lib/system.ml
+++ b/lib/system.ml
@@ -212,37 +212,51 @@ let with_magic_number_check f a =
(* Communication through files with another executable *)
let connect writefun readfun com =
+ (* step 0 : prepare temporary files and I/O channels *)
let name = Filename.basename com in
- let tmp_to = Filename.temp_file ("coq-"^name^"-in") ".xml" in
- let tmp_from = Filename.temp_file ("coq-"^name^"-out") ".xml" in
- let ch_to_in,ch_to_out =
- try open_in tmp_to, open_out tmp_to
+ let req,req_wr =
+ try Filename.open_temp_file ("coq-"^name^"-in") ".xml"
with Sys_error s -> error ("Cannot set connection to "^com^"("^s^")") in
- let ch_from_in,ch_from_out =
- try open_in tmp_from, open_out tmp_from
+ let ans,ans_wr =
+ try Filename.open_temp_file ("coq-"^name^"-out") ".xml"
with Sys_error s ->
- close_out ch_to_out; close_in ch_to_in;
+ close_out req_wr;
error ("Cannot set connection from "^com^"("^s^")") in
- writefun ch_to_out;
- close_out ch_to_out;
+ let ans_wr' = Unix.descr_of_out_channel ans_wr in
+ (* step 1 : fill the request file *)
+ writefun req_wr;
+ close_out req_wr;
+ (* step 2a : prepare the request-reading descriptor for the sub-process *)
+ let req_rd' =
+ try Unix.openfile req [Unix.O_RDONLY] 0o644
+ with Unix.Unix_error (err,_,_) ->
+ close_out ans_wr;
+ let msg = Unix.error_message err in
+ error ("Cannot set connection to "^com^"("^msg^")")
+ in
+ (* step 2b : launch the sub-process *)
let pid =
- let ch_to' = Unix.descr_of_in_channel ch_to_in in
- let ch_from' = Unix.descr_of_out_channel ch_from_out in
- try Unix.create_process com [|com|] ch_to' ch_from' Unix.stdout
+ try Unix.create_process com [|com|] req_rd' ans_wr' Unix.stdout
with Unix.Unix_error (err,_,_) ->
- close_in ch_to_in; close_in ch_from_in; close_out ch_from_out;
- unlink tmp_from; unlink tmp_to;
- error ("Cannot execute "^com^"("^(Unix.error_message err)^")") in
- close_in ch_to_in;
- close_out ch_from_out;
- (match snd (Unix.waitpid [] pid) with
+ Unix.close req_rd'; close_out ans_wr; Unix.unlink req; Unix.unlink ans;
+ let msg = Unix.error_message err in
+ error ("Cannot execute "^com^"("^msg^")") in
+ Unix.close req_rd';
+ close_out ans_wr;
+ (* step 2c : wait for termination of the sub-process *)
+ (match CUnix.waitpid_non_intr pid with
| Unix.WEXITED 127 -> error (com^": cannot execute")
| Unix.WEXITED 0 -> ()
| _ -> error (com^" exited abnormally"));
- let a = readfun ch_from_in in
- close_in ch_from_in;
- unlink tmp_from;
- unlink tmp_to;
+ (* step 3 : read the answer and handle it *)
+ let ans_rd =
+ try open_in ans
+ with Sys_error s -> error ("Cannot read output of "^com^"("^s^")") in
+ let a = readfun ans_rd in
+ close_in ans_rd;
+ (* step 4 : cleanup the temporary files *)
+ unlink req;
+ unlink ans;
a
(* Time stamps. *)
diff --git a/plugins/micromega/mutils.ml b/plugins/micromega/mutils.ml
index 0b98696c9..ae89364e6 100644
--- a/plugins/micromega/mutils.ml
+++ b/plugins/micromega/mutils.ml
@@ -403,6 +403,12 @@ end
module TagSet = Set.Make(Tag)
+(** As for Unix.close_process, our Unix.waipid will ignore all EINTR *)
+
+let rec waitpid_non_intr pid =
+ try snd (Unix.waitpid [] pid)
+ with Unix.Unix_error (Unix.EINTR, _, _) -> waitpid_non_intr pid
+
(**
* Forking routine, plumbing the appropriate pipes where needed.
*)
@@ -422,7 +428,7 @@ let command exe_path args vl =
flush outch ;
(* Wait for its completion *)
- let _pid,status = Unix.waitpid [] pid in
+ let status = waitpid_non_intr pid in
finally
(* Recover the result *)