| author | wenzelm | 
| Sat, 08 Oct 2016 10:59:38 +0200 | |
| changeset 64098 | 099518e8af2c | 
| parent 62923 | 3a122e1e352a | 
| child 64304 | 96bc94c87a81 | 
| 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 | |
| 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 | 9 |   val process: string -> {out: string, err: string, rc: int, terminate: unit -> unit}
 | 
| 44054 | 10 | end; | 
| 11 | ||
| 62911 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 12 | 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 | 13 | \<open> | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 14 | structure Bash: BASH = | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 15 | struct | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 16 | |
| 62923 | 17 | 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 | 18 | let | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 19 | datatype result = Wait | Signal | Result of int; | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 20 | val result = Synchronized.var "bash_result" Wait; | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 21 | |
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 22 | val id = serial_string (); | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 23 |     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 | 24 |     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 | 25 |     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 | 26 |     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 | 27 | |
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 28 | fun cleanup_files () = | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 29 | (try File.rm script_path; | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 30 | try File.rm out_path; | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 31 | try File.rm err_path; | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 32 | try File.rm pid_path); | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 33 | val _ = cleanup_files (); | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 34 | |
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 35 | val system_thread = | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 36 |       Standard_Thread.fork {name = "bash", stack_limit = NONE, interrupts = false} (fn () =>
 | 
| 62923 | 37 | 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 | 38 | let | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 39 | val _ = File.write script_path script; | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 40 | val bash_script = | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 41 | "bash " ^ File.bash_path script_path ^ | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 42 | " > " ^ File.bash_path out_path ^ | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 43 | " 2> " ^ File.bash_path err_path; | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 44 | 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 | 45 | val rc = | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 46 |               Windows.simpleExecute ("",
 | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 47 | quote (ML_System.platform_path bash_process) ^ " " ^ | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 48 | 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 | 49 | |> Windows.fromStatus |> SysWord.toInt; | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 50 | 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 | 51 | in Synchronized.change result (K res) end | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 52 | handle exn => | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 53 | (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 | 54 | |
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 55 | fun read_pid 0 = NONE | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 56 | | read_pid count = | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 57 | (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 | 58 | 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 | 59 | | some => some); | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 60 | |
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 61 | fun terminate NONE = () | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 62 | | terminate (SOME pid) = | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 63 | let | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 64 | fun kill s = | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 65 | let | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 66 | 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 | 67 | 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 | 68 | in | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 69 |                 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 | 70 | handle OS.SysErr _ => false | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 71 | end; | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 72 | |
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 73 | fun multi_kill count s = | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 74 | count = 0 orelse | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 75 | (kill s; kill "0") andalso | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 76 | (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 | 77 | val _ = | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 78 | multi_kill 10 "INT" andalso | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 79 | multi_kill 10 "TERM" andalso | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 80 | multi_kill 10 "KILL"; | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 81 | in () end; | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 82 | |
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 83 | fun cleanup () = | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 84 | (Standard_Thread.interrupt_unsynchronized system_thread; | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 85 | cleanup_files ()); | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 86 | in | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 87 | let | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 88 | val _ = | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 89 | restore_attributes (fn () => | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 90 | 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 | 91 | |
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 92 | 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 | 93 | 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 | 94 | 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 | 95 | val pid = read_pid 1; | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 96 | val _ = cleanup (); | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 97 |     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 | 98 | 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 | 99 | end); | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 100 | |
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 101 | end; | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 102 | \<close> | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 103 | else ML | 
| 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 104 | \<open> | 
| 44054 | 105 | structure Bash: BASH = | 
| 43850 
7f2cbc713344
moved bash operations to Isabelle_System (cf. Scala version);
 wenzelm parents: 
43847diff
changeset | 106 | struct | 
| 
7f2cbc713344
moved bash operations to Isabelle_System (cf. Scala version);
 wenzelm parents: 
43847diff
changeset | 107 | |
| 62923 | 108 | val process = Thread_Attributes.uninterruptible (fn restore_attributes => fn script => | 
| 40749 | 109 | let | 
| 110 | datatype result = Wait | Signal | Result of int; | |
| 111 | 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 | 112 | |
| 40749 | 113 | val id = serial_string (); | 
| 114 |     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 | 115 |     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 | 116 |     val err_path = File.tmp_path (Path.basic ("bash_err" ^ id));
 | 
| 40749 | 117 |     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 | 118 | |
| 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 | 119 | 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 | 120 | (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 | 121 | 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 | 122 | 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 | 123 | 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 | 124 | 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 | 125 | |
| 40749 | 126 | val system_thread = | 
| 61556 | 127 |       Standard_Thread.fork {name = "bash", stack_limit = NONE, interrupts = false} (fn () =>
 | 
| 62923 | 128 | Thread_Attributes.with_attributes Thread_Attributes.private_interrupts (fn _ => | 
| 40749 | 129 | let | 
| 130 | val _ = File.write script_path script; | |
| 62295 | 131 | val _ = getenv_strict "ISABELLE_BASH_PROCESS"; | 
| 40749 | 132 | val status = | 
| 133 | OS.Process.system | |
| 62569 | 134 |                 ("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 | 135 | " 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 | 136 | " > " ^ 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 | 137 | " 2> " ^ File.bash_path err_path); | 
| 40749 | 138 | val res = | 
| 139 | (case Posix.Process.fromStatus status of | |
| 140 | Posix.Process.W_EXITED => Result 0 | |
| 141 | | Posix.Process.W_EXITSTATUS 0wx82 => Signal | |
| 142 | | Posix.Process.W_EXITSTATUS w => Result (Word8.toInt w) | |
| 143 | | Posix.Process.W_SIGNALED s => | |
| 144 | if s = Posix.Signal.int then Signal | |
| 145 | else Result (256 + LargeWord.toInt (Posix.Signal.toWord s)) | |
| 146 | | Posix.Process.W_STOPPED s => | |
| 147 | Result (512 + LargeWord.toInt (Posix.Signal.toWord s))); | |
| 148 | in Synchronized.change result (K res) end | |
| 40783 
21f7e8d66a39
more conventional exception propagation -- taking into account Simple_Thread.fork wrapping;
 wenzelm parents: 
40750diff
changeset | 149 | handle exn => | 
| 62505 | 150 | (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 | 151 | |
| 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 | 152 | 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 | 153 | | 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 | 154 | (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 | 155 | 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 | 156 | | some => some); | 
| 43847 
529159f81d06
more general bash_process, which allows to terminate background processes as well;
 wenzelm parents: 
40896diff
changeset | 157 | |
| 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 | 158 | 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 | 159 | | 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 | 160 | let | 
| 60976 | 161 | 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 | 162 | (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 | 163 | (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 | 164 | 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 | 165 | |
| 
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 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 | 167 | count = 0 orelse | 
| 60976 | 168 | (kill s; kill (Posix.Signal.fromWord 0w0)) andalso | 
| 169 | (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 | 170 | 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 | 171 | 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 | 172 | 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 | 173 | 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 | 174 | in () end; | 
| 40750 
2064991db2ac
more thorough process termination (cf. Scala version);
 wenzelm parents: 
40749diff
changeset | 175 | |
| 40749 | 176 | fun cleanup () = | 
| 61556 | 177 | (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 | 178 | cleanup_files ()); | 
| 40749 | 179 | in | 
| 180 | let | |
| 40748 
591b6778d076
removed bash from ML system bootstrap, and past the Secure ML barrier;
 wenzelm parents: diff
changeset | 181 | val _ = | 
| 40749 | 182 | restore_attributes (fn () => | 
| 40750 
2064991db2ac
more thorough process termination (cf. Scala version);
 wenzelm parents: 
40749diff
changeset | 183 | 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 | 184 | |
| 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 | 185 | 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 | 186 | val err = the_default "" (try File.read err_path); | 
| 40749 | 187 | 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 | 188 | val pid = read_pid 1; | 
| 40749 | 189 | 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 | 190 |     in {out = out, err = err, rc = rc, terminate = fn () => terminate pid} end
 | 
| 62505 | 191 | handle exn => (terminate (read_pid 10); cleanup (); Exn.reraise exn) | 
| 40749 | 192 | end); | 
| 40748 
591b6778d076
removed bash from ML system bootstrap, and past the Secure ML barrier;
 wenzelm parents: diff
changeset | 193 | |
| 43850 
7f2cbc713344
moved bash operations to Isabelle_System (cf. Scala version);
 wenzelm parents: 
43847diff
changeset | 194 | end; | 
| 62911 
78e03d8bf1c4
back to dynamic conditional compilation (reverting 4764473c9b8d) via recursive ML name space;
 wenzelm parents: 
62891diff
changeset | 195 | \<close> |