src/Pure/System/bash.scala
author wenzelm
Sat, 18 Mar 2017 21:40:47 +0100
changeset 65316 c0fb8405416c
parent 64904 14c760e0e1cf
child 65317 b9f5cd845616
permissions -rw-r--r--
simplified signature (despite 448325de6e4f);
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
62584
6cd36a0d2a28 clarified files;
wenzelm
parents: 62574
diff changeset
     1
/*  Title:      Pure/System/bash.scala
60991
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
     2
    Author:     Makarius
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
     3
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
     4
GNU bash processes, with propagation of interrupts.
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
     5
*/
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
     6
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
     7
package isabelle
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
     8
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
     9
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
    10
import java.io.{File => JFile, BufferedReader, InputStreamReader,
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
    11
  BufferedWriter, OutputStreamWriter}
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
    12
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
    13
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
    14
object Bash
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
    15
{
64304
96bc94c87a81 clarified modules;
wenzelm
parents: 63996
diff changeset
    16
  /* concrete syntax */
96bc94c87a81 clarified modules;
wenzelm
parents: 63996
diff changeset
    17
96bc94c87a81 clarified modules;
wenzelm
parents: 63996
diff changeset
    18
  private def bash_chr(c: Byte): String =
96bc94c87a81 clarified modules;
wenzelm
parents: 63996
diff changeset
    19
  {
96bc94c87a81 clarified modules;
wenzelm
parents: 63996
diff changeset
    20
    val ch = c.toChar
96bc94c87a81 clarified modules;
wenzelm
parents: 63996
diff changeset
    21
    ch match {
96bc94c87a81 clarified modules;
wenzelm
parents: 63996
diff changeset
    22
      case '\t' => "$'\\t'"
96bc94c87a81 clarified modules;
wenzelm
parents: 63996
diff changeset
    23
      case '\n' => "$'\\n'"
96bc94c87a81 clarified modules;
wenzelm
parents: 63996
diff changeset
    24
      case '\f' => "$'\\f'"
96bc94c87a81 clarified modules;
wenzelm
parents: 63996
diff changeset
    25
      case '\r' => "$'\\r'"
96bc94c87a81 clarified modules;
wenzelm
parents: 63996
diff changeset
    26
      case _ =>
64904
14c760e0e1cf tuned -- nicer generated bash source;
wenzelm
parents: 64304
diff changeset
    27
        if (Symbol.is_ascii_letter(ch) || Symbol.is_ascii_digit(ch) || "+-./:_".contains(ch))
64304
96bc94c87a81 clarified modules;
wenzelm
parents: 63996
diff changeset
    28
          Symbol.ascii(ch)
96bc94c87a81 clarified modules;
wenzelm
parents: 63996
diff changeset
    29
        else if (c < 0) "$'\\x" + Integer.toHexString(256 + c) + "'"
96bc94c87a81 clarified modules;
wenzelm
parents: 63996
diff changeset
    30
        else if (c < 16) "$'\\x0" + Integer.toHexString(c) + "'"
96bc94c87a81 clarified modules;
wenzelm
parents: 63996
diff changeset
    31
        else if (c < 32 || c >= 127) "$'\\x" + Integer.toHexString(c) + "'"
96bc94c87a81 clarified modules;
wenzelm
parents: 63996
diff changeset
    32
        else  "\\" + ch
96bc94c87a81 clarified modules;
wenzelm
parents: 63996
diff changeset
    33
    }
96bc94c87a81 clarified modules;
wenzelm
parents: 63996
diff changeset
    34
  }
96bc94c87a81 clarified modules;
wenzelm
parents: 63996
diff changeset
    35
96bc94c87a81 clarified modules;
wenzelm
parents: 63996
diff changeset
    36
  def string(s: String): String =
96bc94c87a81 clarified modules;
wenzelm
parents: 63996
diff changeset
    37
    if (s == "") "\"\""
96bc94c87a81 clarified modules;
wenzelm
parents: 63996
diff changeset
    38
    else UTF8.bytes(s).iterator.map(bash_chr(_)).mkString
96bc94c87a81 clarified modules;
wenzelm
parents: 63996
diff changeset
    39
96bc94c87a81 clarified modules;
wenzelm
parents: 63996
diff changeset
    40
  def strings(ss: List[String]): String =
96bc94c87a81 clarified modules;
wenzelm
parents: 63996
diff changeset
    41
    ss.iterator.map(Bash.string(_)).mkString(" ")
96bc94c87a81 clarified modules;
wenzelm
parents: 63996
diff changeset
    42
96bc94c87a81 clarified modules;
wenzelm
parents: 63996
diff changeset
    43
96bc94c87a81 clarified modules;
wenzelm
parents: 63996
diff changeset
    44
  /* process and result */
96bc94c87a81 clarified modules;
wenzelm
parents: 63996
diff changeset
    45
62543
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
    46
  private class Limited_Progress(proc: Process, progress_limit: Option[Long])
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
    47
  {
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
    48
    private var count = 0L
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
    49
    def apply(progress: String => Unit)(line: String): Unit = synchronized {
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
    50
      progress(line)
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
    51
      count = count + line.length + 1
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
    52
      progress_limit match {
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
    53
        case Some(limit) if count > limit => proc.terminate
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
    54
        case _ =>
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
    55
      }
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
    56
    }
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
    57
  }
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
    58
62545
8ebffdaf2ce2 Bash.process always uses a closed script instead of an open argument list, for extra robustness on Windows, where quoting is not well-defined;
wenzelm
parents: 62543
diff changeset
    59
  def process(script: String,
62573
27f90319a499 isabelle.Build uses ML_Process directly;
wenzelm
parents: 62569
diff changeset
    60
      cwd: JFile = null,
62610
4c89504c76fb more uniform signature for various process invocations;
wenzelm
parents: 62604
diff changeset
    61
      env: Map[String, String] = Isabelle_System.settings(),
62602
96e679f042ec more thorough cleanup -- in Scala;
wenzelm
parents: 62584
diff changeset
    62
      redirect: Boolean = false,
96e679f042ec more thorough cleanup -- in Scala;
wenzelm
parents: 62584
diff changeset
    63
      cleanup: () => Unit = () => ()): Process =
96e679f042ec more thorough cleanup -- in Scala;
wenzelm
parents: 62584
diff changeset
    64
    new Process(script, cwd, env, redirect, cleanup)
60991
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
    65
63996
3f47fec9edfc tuned whitespace;
wenzelm
parents: 63805
diff changeset
    66
  class Process private[Bash](
62602
96e679f042ec more thorough cleanup -- in Scala;
wenzelm
parents: 62584
diff changeset
    67
      script: String,
96e679f042ec more thorough cleanup -- in Scala;
wenzelm
parents: 62584
diff changeset
    68
      cwd: JFile,
96e679f042ec more thorough cleanup -- in Scala;
wenzelm
parents: 62584
diff changeset
    69
      env: Map[String, String],
96e679f042ec more thorough cleanup -- in Scala;
wenzelm
parents: 62584
diff changeset
    70
      redirect: Boolean,
96e679f042ec more thorough cleanup -- in Scala;
wenzelm
parents: 62584
diff changeset
    71
      cleanup: () => Unit)
60991
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
    72
  {
62604
wenzelm
parents: 62602
diff changeset
    73
    private val timing_file = Isabelle_System.tmp_file("bash_timing")
62569
5db10482f4cf bash process with builtin timing;
wenzelm
parents: 62558
diff changeset
    74
    private val timing = Synchronized[Option[Timing]](None)
5db10482f4cf bash process with builtin timing;
wenzelm
parents: 62558
diff changeset
    75
5db10482f4cf bash process with builtin timing;
wenzelm
parents: 62558
diff changeset
    76
    private val script_file = Isabelle_System.tmp_file("bash_script")
62545
8ebffdaf2ce2 Bash.process always uses a closed script instead of an open argument list, for extra robustness on Windows, where quoting is not well-defined;
wenzelm
parents: 62543
diff changeset
    77
    File.write(script_file, script)
8ebffdaf2ce2 Bash.process always uses a closed script instead of an open argument list, for extra robustness on Windows, where quoting is not well-defined;
wenzelm
parents: 62543
diff changeset
    78
62296
b04a5ddd6121 clarified bash process -- similar to ML version;
wenzelm
parents: 61025
diff changeset
    79
    private val proc =
62610
4c89504c76fb more uniform signature for various process invocations;
wenzelm
parents: 62604
diff changeset
    80
      Isabelle_System.process(
4c89504c76fb more uniform signature for various process invocations;
wenzelm
parents: 62604
diff changeset
    81
        List(File.platform_path(Path.variable("ISABELLE_BASH_PROCESS")), "-",
4c89504c76fb more uniform signature for various process invocations;
wenzelm
parents: 62604
diff changeset
    82
          File.standard_path(timing_file), "bash", File.standard_path(script_file)),
4c89504c76fb more uniform signature for various process invocations;
wenzelm
parents: 62604
diff changeset
    83
        cwd = cwd, env = env, redirect = redirect)
60991
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
    84
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
    85
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
    86
    // channels
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
    87
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
    88
    val stdin: BufferedWriter =
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
    89
      new BufferedWriter(new OutputStreamWriter(proc.getOutputStream, UTF8.charset))
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
    90
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
    91
    val stdout: BufferedReader =
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
    92
      new BufferedReader(new InputStreamReader(proc.getInputStream, UTF8.charset))
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
    93
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
    94
    val stderr: BufferedReader =
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
    95
      new BufferedReader(new InputStreamReader(proc.getErrorStream, UTF8.charset))
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
    96
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
    97
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
    98
    // signals
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
    99
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   100
    private val pid = stdout.readLine
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   101
62558
c46418f12ee1 clarified process interrupt: exactly one signal (like thread interrupt);
wenzelm
parents: 62545
diff changeset
   102
    def interrupt()
c46418f12ee1 clarified process interrupt: exactly one signal (like thread interrupt);
wenzelm
parents: 62545
diff changeset
   103
    { Exn.Interrupt.postpone { Isabelle_System.kill("INT", pid) } }
c46418f12ee1 clarified process interrupt: exactly one signal (like thread interrupt);
wenzelm
parents: 62545
diff changeset
   104
60991
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   105
    private def kill(signal: String): Boolean =
61025
636b578bfadd clarified kill on Windows: just one executable;
wenzelm
parents: 60991
diff changeset
   106
      Exn.Interrupt.postpone {
636b578bfadd clarified kill on Windows: just one executable;
wenzelm
parents: 60991
diff changeset
   107
        Isabelle_System.kill(signal, pid)
636b578bfadd clarified kill on Windows: just one executable;
wenzelm
parents: 60991
diff changeset
   108
        Isabelle_System.kill("0", pid)._2 == 0 } getOrElse true
60991
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   109
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   110
    private def multi_kill(signal: String): Boolean =
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   111
    {
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   112
      var running = true
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   113
      var count = 10
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   114
      while (running && count > 0) {
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   115
        if (kill(signal)) {
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   116
          Exn.Interrupt.postpone {
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   117
            Thread.sleep(100)
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   118
            count -= 1
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   119
          }
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   120
        }
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   121
        else running = false
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   122
      }
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   123
      running
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   124
    }
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   125
62574
ec382bc689e5 more robust cleanup;
wenzelm
parents: 62573
diff changeset
   126
    def terminate()
ec382bc689e5 more robust cleanup;
wenzelm
parents: 62573
diff changeset
   127
    {
ec382bc689e5 more robust cleanup;
wenzelm
parents: 62573
diff changeset
   128
      multi_kill("INT") && multi_kill("TERM") && kill("KILL")
ec382bc689e5 more robust cleanup;
wenzelm
parents: 62573
diff changeset
   129
      proc.destroy
62602
96e679f042ec more thorough cleanup -- in Scala;
wenzelm
parents: 62584
diff changeset
   130
      do_cleanup()
62574
ec382bc689e5 more robust cleanup;
wenzelm
parents: 62573
diff changeset
   131
    }
60991
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   132
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   133
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   134
    // JVM shutdown hook
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   135
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   136
    private val shutdown_hook = new Thread { override def run = terminate() }
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   137
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   138
    try { Runtime.getRuntime.addShutdownHook(shutdown_hook) }
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   139
    catch { case _: IllegalStateException => }
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   140
62545
8ebffdaf2ce2 Bash.process always uses a closed script instead of an open argument list, for extra robustness on Windows, where quoting is not well-defined;
wenzelm
parents: 62543
diff changeset
   141
62574
ec382bc689e5 more robust cleanup;
wenzelm
parents: 62573
diff changeset
   142
    // cleanup
62545
8ebffdaf2ce2 Bash.process always uses a closed script instead of an open argument list, for extra robustness on Windows, where quoting is not well-defined;
wenzelm
parents: 62543
diff changeset
   143
62602
96e679f042ec more thorough cleanup -- in Scala;
wenzelm
parents: 62584
diff changeset
   144
    private def do_cleanup()
62545
8ebffdaf2ce2 Bash.process always uses a closed script instead of an open argument list, for extra robustness on Windows, where quoting is not well-defined;
wenzelm
parents: 62543
diff changeset
   145
    {
60991
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   146
      try { Runtime.getRuntime.removeShutdownHook(shutdown_hook) }
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   147
      catch { case _: IllegalStateException => }
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   148
62545
8ebffdaf2ce2 Bash.process always uses a closed script instead of an open argument list, for extra robustness on Windows, where quoting is not well-defined;
wenzelm
parents: 62543
diff changeset
   149
      script_file.delete
60991
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   150
62569
5db10482f4cf bash process with builtin timing;
wenzelm
parents: 62558
diff changeset
   151
      timing.change {
5db10482f4cf bash process with builtin timing;
wenzelm
parents: 62558
diff changeset
   152
        case None =>
62574
ec382bc689e5 more robust cleanup;
wenzelm
parents: 62573
diff changeset
   153
          if (timing_file.isFile) {
ec382bc689e5 more robust cleanup;
wenzelm
parents: 62573
diff changeset
   154
            val t =
ec382bc689e5 more robust cleanup;
wenzelm
parents: 62573
diff changeset
   155
              Word.explode(File.read(timing_file)) match {
63805
c272680df665 clarified modules;
wenzelm
parents: 62610
diff changeset
   156
                case List(Value.Long(elapsed), Value.Long(cpu)) =>
62574
ec382bc689e5 more robust cleanup;
wenzelm
parents: 62573
diff changeset
   157
                  Timing(Time.ms(elapsed), Time.ms(cpu), Time.zero)
ec382bc689e5 more robust cleanup;
wenzelm
parents: 62573
diff changeset
   158
                case _ => Timing.zero
ec382bc689e5 more robust cleanup;
wenzelm
parents: 62573
diff changeset
   159
              }
ec382bc689e5 more robust cleanup;
wenzelm
parents: 62573
diff changeset
   160
            timing_file.delete
ec382bc689e5 more robust cleanup;
wenzelm
parents: 62573
diff changeset
   161
            Some(t)
ec382bc689e5 more robust cleanup;
wenzelm
parents: 62573
diff changeset
   162
          }
ec382bc689e5 more robust cleanup;
wenzelm
parents: 62573
diff changeset
   163
          else Some(Timing.zero)
62569
5db10482f4cf bash process with builtin timing;
wenzelm
parents: 62558
diff changeset
   164
        case some => some
5db10482f4cf bash process with builtin timing;
wenzelm
parents: 62558
diff changeset
   165
      }
62602
96e679f042ec more thorough cleanup -- in Scala;
wenzelm
parents: 62584
diff changeset
   166
96e679f042ec more thorough cleanup -- in Scala;
wenzelm
parents: 62584
diff changeset
   167
      cleanup()
62574
ec382bc689e5 more robust cleanup;
wenzelm
parents: 62573
diff changeset
   168
    }
62569
5db10482f4cf bash process with builtin timing;
wenzelm
parents: 62558
diff changeset
   169
62574
ec382bc689e5 more robust cleanup;
wenzelm
parents: 62573
diff changeset
   170
ec382bc689e5 more robust cleanup;
wenzelm
parents: 62573
diff changeset
   171
    // join
ec382bc689e5 more robust cleanup;
wenzelm
parents: 62573
diff changeset
   172
ec382bc689e5 more robust cleanup;
wenzelm
parents: 62573
diff changeset
   173
    def join: Int =
ec382bc689e5 more robust cleanup;
wenzelm
parents: 62573
diff changeset
   174
    {
ec382bc689e5 more robust cleanup;
wenzelm
parents: 62573
diff changeset
   175
      val rc = proc.waitFor
62602
96e679f042ec more thorough cleanup -- in Scala;
wenzelm
parents: 62584
diff changeset
   176
      do_cleanup()
62545
8ebffdaf2ce2 Bash.process always uses a closed script instead of an open argument list, for extra robustness on Windows, where quoting is not well-defined;
wenzelm
parents: 62543
diff changeset
   177
      rc
8ebffdaf2ce2 Bash.process always uses a closed script instead of an open argument list, for extra robustness on Windows, where quoting is not well-defined;
wenzelm
parents: 62543
diff changeset
   178
    }
62543
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
   179
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
   180
62574
ec382bc689e5 more robust cleanup;
wenzelm
parents: 62573
diff changeset
   181
    // result
62543
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
   182
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
   183
    def result(
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
   184
      progress_stdout: String => Unit = (_: String) => (),
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
   185
      progress_stderr: String => Unit = (_: String) => (),
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
   186
      progress_limit: Option[Long] = None,
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
   187
      strict: Boolean = true): Process_Result =
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
   188
    {
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
   189
      stdin.close
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
   190
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
   191
      val limited = new Limited_Progress(this, progress_limit)
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
   192
      val out_lines =
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
   193
        Future.thread("bash_stdout") { File.read_lines(stdout, limited(progress_stdout)) }
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
   194
      val err_lines =
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
   195
        Future.thread("bash_stderr") { File.read_lines(stderr, limited(progress_stderr)) }
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
   196
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
   197
      val rc =
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
   198
        try { join }
62574
ec382bc689e5 more robust cleanup;
wenzelm
parents: 62573
diff changeset
   199
        catch { case Exn.Interrupt() => terminate(); Exn.Interrupt.return_code }
62543
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
   200
      if (strict && rc == Exn.Interrupt.return_code) throw Exn.Interrupt()
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
   201
62574
ec382bc689e5 more robust cleanup;
wenzelm
parents: 62573
diff changeset
   202
      Process_Result(rc, out_lines.join, err_lines.join, false, timing.value getOrElse Timing.zero)
62543
57f379ef662f clarified modules;
wenzelm
parents: 62400
diff changeset
   203
    }
60991
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   204
  }
2fc5a44346b5 clarified modules, like ML version;
wenzelm
parents:
diff changeset
   205
}