moved bash operations to Isabelle_System (cf. Scala version);
1 (* Title: Pure/Concurrent/bash.ML
4 GNU bash processes, with propagation of interrupts.
10 val process = uninterruptible (fn restore_attributes => fn script =>
12 datatype result = Wait | Signal | Result of int;
13 val result = Synchronized.var "bash_result" Wait;
15 val id = serial_string ();
16 val script_path = File.tmp_path (Path.basic ("bash_script" ^ id));
17 val output_path = File.tmp_path (Path.basic ("bash_output" ^ id));
18 val pid_path = File.tmp_path (Path.basic ("bash_pid" ^ id));
21 Simple_Thread.fork false (fn () =>
22 Multithreading.with_attributes Multithreading.private_interrupts (fn _ =>
24 val _ = File.write script_path script;
27 ("exec \"$ISABELLE_HOME/lib/scripts/process\" group " ^
28 File.shell_path pid_path ^ " script \"exec bash " ^
29 File.shell_path script_path ^ " > " ^
30 File.shell_path output_path ^ "\"");
32 (case Posix.Process.fromStatus status of
33 Posix.Process.W_EXITED => Result 0
34 | Posix.Process.W_EXITSTATUS 0wx82 => Signal
35 | Posix.Process.W_EXITSTATUS w => Result (Word8.toInt w)
36 | Posix.Process.W_SIGNALED s =>
37 if s = Posix.Signal.int then Signal
38 else Result (256 + LargeWord.toInt (Posix.Signal.toWord s))
39 | Posix.Process.W_STOPPED s =>
40 Result (512 + LargeWord.toInt (Posix.Signal.toWord s)));
41 in Synchronized.change result (K res) end
43 (Synchronized.change result (fn Wait => Signal | res => res); reraise exn)));
45 fun get_pid () = Int.fromString (File.read pid_path) handle IO.Io _ => NONE;
47 fun terminate opt_pid =
49 val sig_test = Posix.Signal.fromWord 0w0;
51 fun kill_group pid s =
53 (Posix.Process.K_GROUP (Posix.Process.wordToPid (LargeWord.fromInt pid)), s); true)
54 handle OS.SysErr _ => false;
59 | SOME pid => (kill_group pid s; kill_group pid sig_test));
61 fun multi_kill count s =
63 kill s andalso (OS.Process.sleep (seconds 0.1); multi_kill (count - 1) s);
65 multi_kill 10 Posix.Signal.int andalso
66 multi_kill 10 Posix.Signal.term andalso
67 multi_kill 10 Posix.Signal.kill;
71 (Simple_Thread.interrupt system_thread;
72 try File.rm script_path;
73 try File.rm output_path;
74 try File.rm pid_path);
78 restore_attributes (fn () =>
79 Synchronized.guarded_access result (fn Wait => NONE | x => SOME ((), x))) ();
81 val output = the_default "" (try File.read output_path);
82 val rc = (case Synchronized.value result of Signal => Exn.interrupt () | Result rc => rc);
85 in {output = output, rc = rc, terminate = fn () => terminate pid} end
86 handle exn => (terminate (get_pid ()); cleanup (); reraise exn)