| author | wenzelm | 
| Sun, 26 Feb 2012 18:25:28 +0100 | |
| changeset 46684 | 7f741b2c82a3 | 
| parent 44112 | ef876972fdc1 | 
| child 47499 | 4b0daca2bf88 | 
| permissions | -rw-r--r-- | 
| 40748 
591b6778d076
removed bash from ML system bootstrap, and past the Secure ML barrier;
 wenzelm parents: diff
changeset | 1 | (* Title: Pure/Concurrent/bash.ML | 
| 
591b6778d076
removed bash from ML system bootstrap, and past the Secure ML barrier;
 wenzelm parents: diff
changeset | 2 | Author: Makarius | 
| 
591b6778d076
removed bash from ML system bootstrap, and past the Secure ML barrier;
 wenzelm parents: diff
changeset | 3 | |
| 
591b6778d076
removed bash from ML system bootstrap, and past the Secure ML barrier;
 wenzelm parents: diff
changeset | 4 | GNU bash processes, with propagation of interrupts. | 
| 
591b6778d076
removed bash from ML system bootstrap, and past the Secure ML barrier;
 wenzelm parents: diff
changeset | 5 | *) | 
| 
591b6778d076
removed bash from ML system bootstrap, and past the Secure ML barrier;
 wenzelm parents: diff
changeset | 6 | |
| 44054 | 7 | signature BASH = | 
| 8 | sig | |
| 9 |   val process: string -> {output: string, rc: int, terminate: unit -> unit}
 | |
| 10 | end; | |
| 11 | ||
| 12 | structure Bash: BASH = | |
| 43850 
7f2cbc713344
moved bash operations to Isabelle_System (cf. Scala version);
 wenzelm parents: 
43847diff
changeset | 13 | struct | 
| 
7f2cbc713344
moved bash operations to Isabelle_System (cf. Scala version);
 wenzelm parents: 
43847diff
changeset | 14 | |
| 
7f2cbc713344
moved bash operations to Isabelle_System (cf. Scala version);
 wenzelm parents: 
43847diff
changeset | 15 | val process = uninterruptible (fn restore_attributes => fn script => | 
| 40749 | 16 | let | 
| 17 | datatype result = Wait | Signal | Result of int; | |
| 18 | val result = Synchronized.var "bash_result" Wait; | |
| 40748 
591b6778d076
removed bash from ML system bootstrap, and past the Secure ML barrier;
 wenzelm parents: diff
changeset | 19 | |
| 40749 | 20 | val id = serial_string (); | 
| 21 |     val script_path = File.tmp_path (Path.basic ("bash_script" ^ id));
 | |
| 22 |     val output_path = File.tmp_path (Path.basic ("bash_output" ^ id));
 | |
| 23 |     val pid_path = File.tmp_path (Path.basic ("bash_pid" ^ id));
 | |
| 40748 
591b6778d076
removed bash from ML system bootstrap, and past the Secure ML barrier;
 wenzelm parents: diff
changeset | 24 | |
| 40749 | 25 | val system_thread = | 
| 26 | Simple_Thread.fork false (fn () => | |
| 27 | Multithreading.with_attributes Multithreading.private_interrupts (fn _ => | |
| 28 | let | |
| 29 | val _ = File.write script_path script; | |
| 30 | val status = | |
| 31 | OS.Process.system | |
| 32 |                 ("exec \"$ISABELLE_HOME/lib/scripts/process\" group " ^
 | |
| 33 | File.shell_path pid_path ^ " script \"exec bash " ^ | |
| 34 | File.shell_path script_path ^ " > " ^ | |
| 35 | File.shell_path output_path ^ "\""); | |
| 36 | val res = | |
| 37 | (case Posix.Process.fromStatus status of | |
| 38 | Posix.Process.W_EXITED => Result 0 | |
| 39 | | Posix.Process.W_EXITSTATUS 0wx82 => Signal | |
| 40 | | Posix.Process.W_EXITSTATUS w => Result (Word8.toInt w) | |
| 41 | | Posix.Process.W_SIGNALED s => | |
| 42 | if s = Posix.Signal.int then Signal | |
| 43 | else Result (256 + LargeWord.toInt (Posix.Signal.toWord s)) | |
| 44 | | Posix.Process.W_STOPPED s => | |
| 45 | Result (512 + LargeWord.toInt (Posix.Signal.toWord s))); | |
| 46 | in Synchronized.change result (K res) end | |
| 40783 
21f7e8d66a39
more conventional exception propagation -- taking into account Simple_Thread.fork wrapping;
 wenzelm parents: 
40750diff
changeset | 47 | handle exn => | 
| 
21f7e8d66a39
more conventional exception propagation -- taking into account Simple_Thread.fork wrapping;
 wenzelm parents: 
40750diff
changeset | 48 | (Synchronized.change result (fn Wait => Signal | res => res); reraise exn))); | 
| 40748 
591b6778d076
removed bash from ML system bootstrap, and past the Secure ML barrier;
 wenzelm parents: diff
changeset | 49 | |
| 43847 
529159f81d06
more general bash_process, which allows to terminate background processes as well;
 wenzelm parents: 
40896diff
changeset | 50 | fun get_pid () = Int.fromString (File.read pid_path) handle IO.Io _ => NONE; | 
| 
529159f81d06
more general bash_process, which allows to terminate background processes as well;
 wenzelm parents: 
40896diff
changeset | 51 | |
| 
529159f81d06
more general bash_process, which allows to terminate background processes as well;
 wenzelm parents: 
40896diff
changeset | 52 | fun terminate opt_pid = | 
| 40750 
2064991db2ac
more thorough process termination (cf. Scala version);
 wenzelm parents: 
40749diff
changeset | 53 | let | 
| 
2064991db2ac
more thorough process termination (cf. Scala version);
 wenzelm parents: 
40749diff
changeset | 54 | val sig_test = Posix.Signal.fromWord 0w0; | 
| 
2064991db2ac
more thorough process termination (cf. Scala version);
 wenzelm parents: 
40749diff
changeset | 55 | |
| 
2064991db2ac
more thorough process termination (cf. Scala version);
 wenzelm parents: 
40749diff
changeset | 56 | fun kill_group pid s = | 
| 
2064991db2ac
more thorough process termination (cf. Scala version);
 wenzelm parents: 
40749diff
changeset | 57 | (Posix.Process.kill | 
| 
2064991db2ac
more thorough process termination (cf. Scala version);
 wenzelm parents: 
40749diff
changeset | 58 | (Posix.Process.K_GROUP (Posix.Process.wordToPid (LargeWord.fromInt pid)), s); true) | 
| 
2064991db2ac
more thorough process termination (cf. Scala version);
 wenzelm parents: 
40749diff
changeset | 59 | handle OS.SysErr _ => false; | 
| 
2064991db2ac
more thorough process termination (cf. Scala version);
 wenzelm parents: 
40749diff
changeset | 60 | |
| 
2064991db2ac
more thorough process termination (cf. Scala version);
 wenzelm parents: 
40749diff
changeset | 61 | fun kill s = | 
| 43847 
529159f81d06
more general bash_process, which allows to terminate background processes as well;
 wenzelm parents: 
40896diff
changeset | 62 | (case opt_pid of | 
| 40750 
2064991db2ac
more thorough process termination (cf. Scala version);
 wenzelm parents: 
40749diff
changeset | 63 | NONE => true | 
| 43847 
529159f81d06
more general bash_process, which allows to terminate background processes as well;
 wenzelm parents: 
40896diff
changeset | 64 | | SOME pid => (kill_group pid s; kill_group pid sig_test)); | 
| 40750 
2064991db2ac
more thorough process termination (cf. Scala version);
 wenzelm parents: 
40749diff
changeset | 65 | |
| 
2064991db2ac
more thorough process termination (cf. Scala version);
 wenzelm parents: 
40749diff
changeset | 66 | fun multi_kill count s = | 
| 
2064991db2ac
more thorough process termination (cf. Scala version);
 wenzelm parents: 
40749diff
changeset | 67 | count = 0 orelse | 
| 
2064991db2ac
more thorough process termination (cf. Scala version);
 wenzelm parents: 
40749diff
changeset | 68 | kill s andalso (OS.Process.sleep (seconds 0.1); multi_kill (count - 1) s); | 
| 
2064991db2ac
more thorough process termination (cf. Scala version);
 wenzelm parents: 
40749diff
changeset | 69 | val _ = | 
| 
2064991db2ac
more thorough process termination (cf. Scala version);
 wenzelm parents: 
40749diff
changeset | 70 | multi_kill 10 Posix.Signal.int andalso | 
| 
2064991db2ac
more thorough process termination (cf. Scala version);
 wenzelm parents: 
40749diff
changeset | 71 | multi_kill 10 Posix.Signal.term andalso | 
| 
2064991db2ac
more thorough process termination (cf. Scala version);
 wenzelm parents: 
40749diff
changeset | 72 | multi_kill 10 Posix.Signal.kill; | 
| 
2064991db2ac
more thorough process termination (cf. Scala version);
 wenzelm parents: 
40749diff
changeset | 73 | in () end; | 
| 
2064991db2ac
more thorough process termination (cf. Scala version);
 wenzelm parents: 
40749diff
changeset | 74 | |
| 40749 | 75 | fun cleanup () = | 
| 44112 
ef876972fdc1
more explicit Simple_Thread.interrupt_unsynchronized, to emphasize its meaning;
 wenzelm parents: 
44054diff
changeset | 76 | (Simple_Thread.interrupt_unsynchronized system_thread; | 
| 40749 | 77 | try File.rm script_path; | 
| 78 | try File.rm output_path; | |
| 79 | try File.rm pid_path); | |
| 80 | in | |
| 81 | let | |
| 40748 
591b6778d076
removed bash from ML system bootstrap, and past the Secure ML barrier;
 wenzelm parents: diff
changeset | 82 | val _ = | 
| 40749 | 83 | restore_attributes (fn () => | 
| 40750 
2064991db2ac
more thorough process termination (cf. Scala version);
 wenzelm parents: 
40749diff
changeset | 84 | Synchronized.guarded_access result (fn Wait => NONE | x => SOME ((), x))) (); | 
| 40748 
591b6778d076
removed bash from ML system bootstrap, and past the Secure ML barrier;
 wenzelm parents: diff
changeset | 85 | |
| 40749 | 86 | val output = the_default "" (try File.read output_path); | 
| 87 | val rc = (case Synchronized.value result of Signal => Exn.interrupt () | Result rc => rc); | |
| 43847 
529159f81d06
more general bash_process, which allows to terminate background processes as well;
 wenzelm parents: 
40896diff
changeset | 88 | val pid = get_pid (); | 
| 40749 | 89 | val _ = cleanup (); | 
| 43847 
529159f81d06
more general bash_process, which allows to terminate background processes as well;
 wenzelm parents: 
40896diff
changeset | 90 |     in {output = output, rc = rc, terminate = fn () => terminate pid} end
 | 
| 
529159f81d06
more general bash_process, which allows to terminate background processes as well;
 wenzelm parents: 
40896diff
changeset | 91 | handle exn => (terminate (get_pid ()); cleanup (); reraise exn) | 
| 40749 | 92 | end); | 
| 40748 
591b6778d076
removed bash from ML system bootstrap, and past the Secure ML barrier;
 wenzelm parents: diff
changeset | 93 | |
| 43850 
7f2cbc713344
moved bash operations to Isabelle_System (cf. Scala version);
 wenzelm parents: 
43847diff
changeset | 94 | end; | 
| 
7f2cbc713344
moved bash operations to Isabelle_System (cf. Scala version);
 wenzelm parents: 
43847diff
changeset | 95 |