| author | wenzelm | 
| Sat, 25 Nov 2017 15:22:17 +0100 | |
| changeset 67089 | c96ee0eb0d5f | 
| parent 64304 | 96bc94c87a81 | 
| child 71692 | f8e52c0152fe | 
| permissions | -rw-r--r-- | 
| 62584 | 1 | (* Title: Pure/System/bash.ML | 
| 40748 
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 | |
| 62879 
4764473c9b8d
back to static conditional compilation -- simplified bootstrap;
 wenzelm parents: 
62850diff
changeset | 4 | GNU bash processes, with propagation of interrupts -- POSIX version. | 
| 40748 
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 | |
| 64304 | 9 | val string: string -> string | 
| 10 | val strings: string list -> string | |
| 47499 
4b0daca2bf88
redirect bash stderr to Isabelle warning as appropriate -- avoid raw process error output which may either get ignored or overload PIDE syslog in extreme cases;
 wenzelm parents: 
44112diff
changeset | 11 |   val process: string -> {out: string, err: string, rc: int, terminate: unit -> unit}
 | 
| 44054 | 12 | end; | 
| 13 | ||
| 62911 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 14 | if ML_System.platform_is_windows then ML | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 15 | \<open> | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 16 | structure Bash: BASH = | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 17 | struct | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 18 | |
| 64304 | 19 | val string = Bash_Syntax.string; | 
| 20 | val strings = Bash_Syntax.strings; | |
| 21 | ||
| 62923 | 22 | val process = Thread_Attributes.uninterruptible (fn restore_attributes => fn script => | 
| 62911 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 23 | let | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 24 | datatype result = Wait | Signal | Result of int; | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 25 | val result = Synchronized.var "bash_result" Wait; | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 26 | |
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 27 | val id = serial_string (); | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 28 |     val script_path = File.tmp_path (Path.basic ("bash_script" ^ id));
 | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 29 |     val out_path = File.tmp_path (Path.basic ("bash_out" ^ id));
 | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 30 |     val err_path = File.tmp_path (Path.basic ("bash_err" ^ id));
 | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 31 |     val pid_path = File.tmp_path (Path.basic ("bash_pid" ^ id));
 | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 32 | |
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 33 | fun cleanup_files () = | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 34 | (try File.rm script_path; | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 35 | try File.rm out_path; | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 36 | try File.rm err_path; | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 37 | try File.rm pid_path); | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 38 | val _ = cleanup_files (); | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 39 | |
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 40 | val system_thread = | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 41 |       Standard_Thread.fork {name = "bash", stack_limit = NONE, interrupts = false} (fn () =>
 | 
| 62923 | 42 | Thread_Attributes.with_attributes Thread_Attributes.private_interrupts (fn _ => | 
| 62911 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 43 | let | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 44 | val _ = File.write script_path script; | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 45 | val bash_script = | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 46 | "bash " ^ File.bash_path script_path ^ | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 47 | " > " ^ File.bash_path out_path ^ | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 48 | " 2> " ^ File.bash_path err_path; | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 49 | val bash_process = getenv_strict "ISABELLE_BASH_PROCESS"; | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 50 | val rc = | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 51 |               Windows.simpleExecute ("",
 | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 52 | quote (ML_System.platform_path bash_process) ^ " " ^ | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 53 | quote (File.platform_path pid_path) ^ " \"\" bash -c " ^ quote bash_script) | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 54 | |> Windows.fromStatus |> SysWord.toInt; | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 55 | val res = if rc = 130 orelse rc = 512 then Signal else Result rc; | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 56 | in Synchronized.change result (K res) end | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 57 | handle exn => | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 58 | (Synchronized.change result (fn Wait => Signal | res => res); Exn.reraise exn))); | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 59 | |
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 60 | fun read_pid 0 = NONE | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 61 | | read_pid count = | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 62 | (case (Int.fromString (File.read pid_path) handle IO.Io _ => NONE) of | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 63 | NONE => (OS.Process.sleep (seconds 0.1); read_pid (count - 1)) | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 64 | | some => some); | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 65 | |
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 66 | fun terminate NONE = () | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 67 | | terminate (SOME pid) = | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 68 | let | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 69 | fun kill s = | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 70 | let | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 71 | val cmd = getenv_strict "CYGWIN_ROOT" ^ "\\bin\\bash.exe"; | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 72 | val arg = "kill -" ^ s ^ " -" ^ string_of_int pid; | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 73 | in | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 74 |                 OS.Process.isSuccess (Windows.simpleExecute ("", quote cmd ^ " -c " ^ quote arg))
 | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 75 | handle OS.SysErr _ => false | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 76 | end; | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 77 | |
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 78 | fun multi_kill count s = | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 79 | count = 0 orelse | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 80 | (kill s; kill "0") andalso | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 81 | (OS.Process.sleep (seconds 0.1); multi_kill (count - 1) s); | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 82 | val _ = | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 83 | multi_kill 10 "INT" andalso | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 84 | multi_kill 10 "TERM" andalso | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 85 | multi_kill 10 "KILL"; | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 86 | in () end; | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 87 | |
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 88 | fun cleanup () = | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 89 | (Standard_Thread.interrupt_unsynchronized system_thread; | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 90 | cleanup_files ()); | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 91 | in | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 92 | let | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 93 | val _ = | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 94 | restore_attributes (fn () => | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 95 | Synchronized.guarded_access result (fn Wait => NONE | x => SOME ((), x))) (); | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 96 | |
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 97 | val out = the_default "" (try File.read out_path); | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 98 | val err = the_default "" (try File.read err_path); | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 99 | val rc = (case Synchronized.value result of Signal => Exn.interrupt () | Result rc => rc); | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 100 | val pid = read_pid 1; | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 101 | val _ = cleanup (); | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 102 |     in {out = out, err = err, rc = rc, terminate = fn () => terminate pid} end
 | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 103 | handle exn => (terminate (read_pid 10); cleanup (); Exn.reraise exn) | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 104 | end); | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 105 | |
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 106 | end; | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 107 | \<close> | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 108 | else ML | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 109 | \<open> | 
| 44054 | 110 | structure Bash: BASH = | 
| 43850 
7f2cbc713344
moved bash operations to Isabelle_System (cf. Scala version);
 wenzelm parents: 
43847diff
changeset | 111 | struct | 
| 
7f2cbc713344
moved bash operations to Isabelle_System (cf. Scala version);
 wenzelm parents: 
43847diff
changeset | 112 | |
| 64304 | 113 | val string = Bash_Syntax.string; | 
| 114 | val strings = Bash_Syntax.strings; | |
| 115 | ||
| 62923 | 116 | val process = Thread_Attributes.uninterruptible (fn restore_attributes => fn script => | 
| 40749 | 117 | let | 
| 118 | datatype result = Wait | Signal | Result of int; | |
| 119 | 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 | 120 | |
| 40749 | 121 | val id = serial_string (); | 
| 122 |     val script_path = File.tmp_path (Path.basic ("bash_script" ^ id));
 | |
| 47499 
4b0daca2bf88
redirect bash stderr to Isabelle warning as appropriate -- avoid raw process error output which may either get ignored or overload PIDE syslog in extreme cases;
 wenzelm parents: 
44112diff
changeset | 123 |     val out_path = File.tmp_path (Path.basic ("bash_out" ^ id));
 | 
| 
4b0daca2bf88
redirect bash stderr to Isabelle warning as appropriate -- avoid raw process error output which may either get ignored or overload PIDE syslog in extreme cases;
 wenzelm parents: 
44112diff
changeset | 124 |     val err_path = File.tmp_path (Path.basic ("bash_err" ^ id));
 | 
| 40749 | 125 |     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 | 126 | |
| 54651 
d71e7908eec3
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;
 wenzelm parents: 
47764diff
changeset | 127 | fun cleanup_files () = | 
| 
d71e7908eec3
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;
 wenzelm parents: 
47764diff
changeset | 128 | (try File.rm script_path; | 
| 
d71e7908eec3
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;
 wenzelm parents: 
47764diff
changeset | 129 | try File.rm out_path; | 
| 
d71e7908eec3
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;
 wenzelm parents: 
47764diff
changeset | 130 | try File.rm err_path; | 
| 
d71e7908eec3
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;
 wenzelm parents: 
47764diff
changeset | 131 | try File.rm pid_path); | 
| 
d71e7908eec3
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;
 wenzelm parents: 
47764diff
changeset | 132 | val _ = cleanup_files (); | 
| 
d71e7908eec3
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;
 wenzelm parents: 
47764diff
changeset | 133 | |
| 40749 | 134 | val system_thread = | 
| 61556 | 135 |       Standard_Thread.fork {name = "bash", stack_limit = NONE, interrupts = false} (fn () =>
 | 
| 62923 | 136 | Thread_Attributes.with_attributes Thread_Attributes.private_interrupts (fn _ => | 
| 40749 | 137 | let | 
| 138 | val _ = File.write script_path script; | |
| 62295 | 139 | val _ = getenv_strict "ISABELLE_BASH_PROCESS"; | 
| 40749 | 140 | val status = | 
| 141 | OS.Process.system | |
| 62569 | 142 |                 ("exec \"$ISABELLE_BASH_PROCESS\" " ^ File.bash_path pid_path ^ " \"\"" ^
 | 
| 62549 
9498623b27f0
File.bash_string operations in ML as in Scala -- exclusively for GNU bash, not perl and not user output;
 wenzelm parents: 
62505diff
changeset | 143 | " bash " ^ File.bash_path script_path ^ | 
| 
9498623b27f0
File.bash_string operations in ML as in Scala -- exclusively for GNU bash, not perl and not user output;
 wenzelm parents: 
62505diff
changeset | 144 | " > " ^ File.bash_path out_path ^ | 
| 
9498623b27f0
File.bash_string operations in ML as in Scala -- exclusively for GNU bash, not perl and not user output;
 wenzelm parents: 
62505diff
changeset | 145 | " 2> " ^ File.bash_path err_path); | 
| 40749 | 146 | val res = | 
| 147 | (case Posix.Process.fromStatus status of | |
| 148 | Posix.Process.W_EXITED => Result 0 | |
| 149 | | Posix.Process.W_EXITSTATUS 0wx82 => Signal | |
| 150 | | Posix.Process.W_EXITSTATUS w => Result (Word8.toInt w) | |
| 151 | | Posix.Process.W_SIGNALED s => | |
| 152 | if s = Posix.Signal.int then Signal | |
| 153 | else Result (256 + LargeWord.toInt (Posix.Signal.toWord s)) | |
| 154 | | Posix.Process.W_STOPPED s => | |
| 155 | Result (512 + LargeWord.toInt (Posix.Signal.toWord s))); | |
| 156 | in Synchronized.change result (K res) end | |
| 40783 
21f7e8d66a39
more conventional exception propagation -- taking into account Simple_Thread.fork wrapping;
 wenzelm parents: 
40750diff
changeset | 157 | handle exn => | 
| 62505 | 158 | (Synchronized.change result (fn Wait => Signal | res => res); Exn.reraise exn))); | 
| 40748 
591b6778d076
removed bash from ML system bootstrap, and past the Secure ML barrier;
 wenzelm parents: diff
changeset | 159 | |
| 54651 
d71e7908eec3
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;
 wenzelm parents: 
47764diff
changeset | 160 | fun read_pid 0 = NONE | 
| 
d71e7908eec3
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;
 wenzelm parents: 
47764diff
changeset | 161 | | read_pid count = | 
| 
d71e7908eec3
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;
 wenzelm parents: 
47764diff
changeset | 162 | (case (Int.fromString (File.read pid_path) handle IO.Io _ => NONE) of | 
| 
d71e7908eec3
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;
 wenzelm parents: 
47764diff
changeset | 163 | NONE => (OS.Process.sleep (seconds 0.1); read_pid (count - 1)) | 
| 
d71e7908eec3
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;
 wenzelm parents: 
47764diff
changeset | 164 | | some => some); | 
| 43847 
529159f81d06
more general bash_process, which allows to terminate background processes as well;
 wenzelm parents: 
40896diff
changeset | 165 | |
| 54651 
d71e7908eec3
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;
 wenzelm parents: 
47764diff
changeset | 166 | fun terminate NONE = () | 
| 
d71e7908eec3
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;
 wenzelm parents: 
47764diff
changeset | 167 | | terminate (SOME pid) = | 
| 
d71e7908eec3
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;
 wenzelm parents: 
47764diff
changeset | 168 | let | 
| 60976 | 169 | fun kill s = | 
| 54651 
d71e7908eec3
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;
 wenzelm parents: 
47764diff
changeset | 170 | (Posix.Process.kill | 
| 
d71e7908eec3
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;
 wenzelm parents: 
47764diff
changeset | 171 | (Posix.Process.K_GROUP (Posix.Process.wordToPid (LargeWord.fromInt pid)), s); true) | 
| 
d71e7908eec3
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;
 wenzelm parents: 
47764diff
changeset | 172 | handle OS.SysErr _ => false; | 
| 
d71e7908eec3
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;
 wenzelm parents: 
47764diff
changeset | 173 | |
| 
d71e7908eec3
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;
 wenzelm parents: 
47764diff
changeset | 174 | fun multi_kill count s = | 
| 
d71e7908eec3
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;
 wenzelm parents: 
47764diff
changeset | 175 | count = 0 orelse | 
| 60976 | 176 | (kill s; kill (Posix.Signal.fromWord 0w0)) andalso | 
| 177 | (OS.Process.sleep (seconds 0.1); multi_kill (count - 1) s); | |
| 54651 
d71e7908eec3
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;
 wenzelm parents: 
47764diff
changeset | 178 | val _ = | 
| 
d71e7908eec3
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;
 wenzelm parents: 
47764diff
changeset | 179 | multi_kill 10 Posix.Signal.int andalso | 
| 
d71e7908eec3
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;
 wenzelm parents: 
47764diff
changeset | 180 | multi_kill 10 Posix.Signal.term andalso | 
| 
d71e7908eec3
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;
 wenzelm parents: 
47764diff
changeset | 181 | multi_kill 10 Posix.Signal.kill; | 
| 
d71e7908eec3
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;
 wenzelm parents: 
47764diff
changeset | 182 | in () end; | 
| 40750 
2064991db2ac
more thorough process termination (cf. Scala version);
 wenzelm parents: 
40749diff
changeset | 183 | |
| 40749 | 184 | fun cleanup () = | 
| 61556 | 185 | (Standard_Thread.interrupt_unsynchronized system_thread; | 
| 54651 
d71e7908eec3
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;
 wenzelm parents: 
47764diff
changeset | 186 | cleanup_files ()); | 
| 40749 | 187 | in | 
| 188 | let | |
| 40748 
591b6778d076
removed bash from ML system bootstrap, and past the Secure ML barrier;
 wenzelm parents: diff
changeset | 189 | val _ = | 
| 40749 | 190 | restore_attributes (fn () => | 
| 40750 
2064991db2ac
more thorough process termination (cf. Scala version);
 wenzelm parents: 
40749diff
changeset | 191 | 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 | 192 | |
| 47499 
4b0daca2bf88
redirect bash stderr to Isabelle warning as appropriate -- avoid raw process error output which may either get ignored or overload PIDE syslog in extreme cases;
 wenzelm parents: 
44112diff
changeset | 193 | val out = the_default "" (try File.read out_path); | 
| 
4b0daca2bf88
redirect bash stderr to Isabelle warning as appropriate -- avoid raw process error output which may either get ignored or overload PIDE syslog in extreme cases;
 wenzelm parents: 
44112diff
changeset | 194 | val err = the_default "" (try File.read err_path); | 
| 40749 | 195 | val rc = (case Synchronized.value result of Signal => Exn.interrupt () | Result rc => rc); | 
| 54651 
d71e7908eec3
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;
 wenzelm parents: 
47764diff
changeset | 196 | val pid = read_pid 1; | 
| 40749 | 197 | val _ = cleanup (); | 
| 47499 
4b0daca2bf88
redirect bash stderr to Isabelle warning as appropriate -- avoid raw process error output which may either get ignored or overload PIDE syslog in extreme cases;
 wenzelm parents: 
44112diff
changeset | 198 |     in {out = out, err = err, rc = rc, terminate = fn () => terminate pid} end
 | 
| 62505 | 199 | handle exn => (terminate (read_pid 10); cleanup (); Exn.reraise exn) | 
| 40749 | 200 | end); | 
| 40748 
591b6778d076
removed bash from ML system bootstrap, and past the Secure ML barrier;
 wenzelm parents: diff
changeset | 201 | |
| 43850 
7f2cbc713344
moved bash operations to Isabelle_System (cf. Scala version);
 wenzelm parents: 
43847diff
changeset | 202 | end; | 
| 62911 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 203 | \<close> |