more thorough read_pid with extra delay, to give external process a chance to write pid file before attempting to terminate it -- especially relevant for PIDE document processing, where interrupts can happen in the range of milliseconds;
--- a/src/Pure/Concurrent/bash.ML Thu Nov 28 13:59:00 2013 +0100
+++ b/src/Pure/Concurrent/bash.ML Sat Nov 30 15:05:10 2013 +0100
@@ -23,6 +23,13 @@
val err_path = File.tmp_path (Path.basic ("bash_err" ^ id));
val pid_path = File.tmp_path (Path.basic ("bash_pid" ^ id));
+ fun cleanup_files () =
+ (try File.rm script_path;
+ try File.rm out_path;
+ try File.rm err_path;
+ try File.rm pid_path);
+ val _ = cleanup_files ();
+
val system_thread =
Simple_Thread.fork false (fn () =>
Multithreading.with_attributes Multithreading.private_interrupts (fn _ =>
@@ -55,37 +62,36 @@
handle exn =>
(Synchronized.change result (fn Wait => Signal | res => res); reraise exn)));
- fun get_pid () = Int.fromString (File.read pid_path) handle IO.Io _ => NONE;
+ fun read_pid 0 = NONE
+ | read_pid count =
+ (case (Int.fromString (File.read pid_path) handle IO.Io _ => NONE) of
+ NONE => (OS.Process.sleep (seconds 0.1); read_pid (count - 1))
+ | some => some);
- fun terminate opt_pid =
- let
- val sig_test = Posix.Signal.fromWord 0w0;
-
- fun kill_group pid s =
- (Posix.Process.kill
- (Posix.Process.K_GROUP (Posix.Process.wordToPid (LargeWord.fromInt pid)), s); true)
- handle OS.SysErr _ => false;
+ fun terminate NONE = ()
+ | terminate (SOME pid) =
+ let
+ val sig_test = Posix.Signal.fromWord 0w0;
- fun kill s =
- (case opt_pid of
- NONE => true
- | SOME pid => (kill_group pid s; kill_group pid sig_test));
+ fun kill_group pid s =
+ (Posix.Process.kill
+ (Posix.Process.K_GROUP (Posix.Process.wordToPid (LargeWord.fromInt pid)), s); true)
+ handle OS.SysErr _ => false;
+
+ fun kill s = (kill_group pid s; kill_group pid sig_test);
- fun multi_kill count s =
- count = 0 orelse
- kill s andalso (OS.Process.sleep (seconds 0.1); multi_kill (count - 1) s);
- val _ =
- multi_kill 10 Posix.Signal.int andalso
- multi_kill 10 Posix.Signal.term andalso
- multi_kill 10 Posix.Signal.kill;
- in () end;
+ fun multi_kill count s =
+ count = 0 orelse
+ kill s andalso (OS.Process.sleep (seconds 0.1); multi_kill (count - 1) s);
+ val _ =
+ multi_kill 10 Posix.Signal.int andalso
+ multi_kill 10 Posix.Signal.term andalso
+ multi_kill 10 Posix.Signal.kill;
+ in () end;
fun cleanup () =
(Simple_Thread.interrupt_unsynchronized system_thread;
- try File.rm script_path;
- try File.rm out_path;
- try File.rm err_path;
- try File.rm pid_path);
+ cleanup_files ());
in
let
val _ =
@@ -95,10 +101,10 @@
val out = the_default "" (try File.read out_path);
val err = the_default "" (try File.read err_path);
val rc = (case Synchronized.value result of Signal => Exn.interrupt () | Result rc => rc);
- val pid = get_pid ();
+ val pid = read_pid 1;
val _ = cleanup ();
in {out = out, err = err, rc = rc, terminate = fn () => terminate pid} end
- handle exn => (terminate (get_pid ()); cleanup (); reraise exn)
+ handle exn => (terminate (read_pid 10); cleanup (); reraise exn)
end);
end;