main Isabelle_Process via Isabelle_System.Managed_Process;
authorwenzelm
Wed, 22 Sep 2010 13:47:48 +0200
changeset 3984900be8711082f
parent 39848 f2a10986e85a
child 39850 ea8f3ea13a95
main Isabelle_Process via Isabelle_System.Managed_Process;
simplified init message: no pid;
misc tuning and simplification;
src/Pure/General/markup.ML
src/Pure/General/markup.scala
src/Pure/ML-Systems/polyml_common.ML
src/Pure/ML-Systems/smlnj.ML
src/Pure/System/isabelle_process.ML
src/Pure/System/isabelle_process.scala
src/Pure/System/session.scala
     1.1 --- a/src/Pure/General/markup.ML	Wed Sep 22 12:52:35 2010 +0200
     1.2 +++ b/src/Pure/General/markup.ML	Wed Sep 22 13:47:48 2010 +0200
     1.3 @@ -114,7 +114,6 @@
     1.4    val execN: string
     1.5    val assignN: string val assign: int -> T
     1.6    val editN: string val edit: int -> int -> T
     1.7 -  val pidN: string
     1.8    val serialN: string
     1.9    val promptN: string val prompt: T
    1.10    val readyN: string val ready: T
    1.11 @@ -340,7 +339,6 @@
    1.12  
    1.13  (* messages *)
    1.14  
    1.15 -val pidN = "pid";
    1.16  val serialN = "serial";
    1.17  
    1.18  val (promptN, prompt) = markup_elem "prompt";
     2.1 --- a/src/Pure/General/markup.scala	Wed Sep 22 12:52:35 2010 +0200
     2.2 +++ b/src/Pure/General/markup.scala	Wed Sep 22 13:47:48 2010 +0200
     2.3 @@ -227,7 +227,6 @@
     2.4  
     2.5    /* messages */
     2.6  
     2.7 -  val PID = "pid"
     2.8    val Serial = new Long_Property("serial")
     2.9  
    2.10    val MESSAGE = "message"
     3.1 --- a/src/Pure/ML-Systems/polyml_common.ML	Wed Sep 22 12:52:35 2010 +0200
     3.2 +++ b/src/Pure/ML-Systems/polyml_common.ML	Wed Sep 22 13:47:48 2010 +0200
     3.3 @@ -111,9 +111,6 @@
     3.4  val cd = OS.FileSys.chDir;
     3.5  val pwd = OS.FileSys.getDir;
     3.6  
     3.7 -fun process_id () =
     3.8 -  Word.fmt StringCvt.DEC (Word.fromLargeWord (Posix.Process.pidToWord (Posix.ProcEnv.getpid ())));
     3.9 -
    3.10  
    3.11  (* getenv *)
    3.12  
     4.1 --- a/src/Pure/ML-Systems/smlnj.ML	Wed Sep 22 12:52:35 2010 +0200
     4.2 +++ b/src/Pure/ML-Systems/smlnj.ML	Wed Sep 22 13:47:48 2010 +0200
     4.3 @@ -172,9 +172,6 @@
     4.4  
     4.5  val bash_output = (fn (output, rc) => (output, mk_int rc)) o bash_output;
     4.6  
     4.7 -fun process_id pid =
     4.8 -  Word.fmt StringCvt.DEC (Word.fromLargeWord (Posix.Process.pidToWord (Posix.ProcEnv.getpid ())));
     4.9 -
    4.10  
    4.11  (* getenv *)
    4.12  
     5.1 --- a/src/Pure/System/isabelle_process.ML	Wed Sep 22 12:52:35 2010 +0200
     5.2 +++ b/src/Pure/System/isabelle_process.ML	Wed Sep 22 13:47:48 2010 +0200
     5.3 @@ -78,7 +78,7 @@
     5.4        (Position.properties_of (Position.thread_data ()))) body;
     5.5  
     5.6  fun init_message out_stream =
     5.7 -  message out_stream "A" [(Markup.pidN, process_id ())] (Session.welcome ());
     5.8 +  message out_stream "A" [] (Session.welcome ());
     5.9  
    5.10  end;
    5.11  
     6.1 --- a/src/Pure/System/isabelle_process.scala	Wed Sep 22 12:52:35 2010 +0200
     6.2 +++ b/src/Pure/System/isabelle_process.scala	Wed Sep 22 13:47:48 2010 +0200
     6.3 @@ -92,14 +92,7 @@
     6.4  
     6.5    private def put_result(kind: String, props: List[(String, String)], body: XML.Body)
     6.6    {
     6.7 -    if (pid.isEmpty && kind == Markup.INIT) {
     6.8 -      rm_fifos()
     6.9 -      props.find(_._1 == Markup.PID).map(_._1) match {
    6.10 -        case None => system_result("Bad Isabelle process initialization: missing pid")
    6.11 -        case p => pid = p
    6.12 -      }
    6.13 -    }
    6.14 -
    6.15 +    if (kind == Markup.INIT) rm_fifos()
    6.16      val msg = XML.Elem(Markup(kind, props), Isar_Document.clean_message(body))
    6.17      xml_cache.cache_tree(msg)((message: XML.Tree) =>
    6.18        receiver ! new Result(message.asInstanceOf[XML.Elem]))
    6.19 @@ -117,33 +110,39 @@
    6.20    private case class Input_Chunks(chunks: List[Array[Byte]])
    6.21  
    6.22    private case object Close
    6.23 -  private def close(a: Actor) { if (a != null) a ! Close }
    6.24 +  private def close(p: (Thread, Actor))
    6.25 +  {
    6.26 +    if (p != null && p._1.isAlive) {
    6.27 +      p._2 ! Close
    6.28 +      p._1.join
    6.29 +    }
    6.30 +  }
    6.31  
    6.32 -  @volatile private var standard_input: Actor = null
    6.33 -  @volatile private var command_input: Actor = null
    6.34 +  @volatile private var standard_input: (Thread, Actor) = null
    6.35 +  @volatile private var command_input: (Thread, Actor) = null
    6.36  
    6.37  
    6.38 -  /* process manager */
    6.39 +  /** process manager **/
    6.40  
    6.41    private val in_fifo = system.mk_fifo()
    6.42    private val out_fifo = system.mk_fifo()
    6.43    private def rm_fifos() { system.rm_fifo(in_fifo); system.rm_fifo(out_fifo) }
    6.44  
    6.45 -  private val proc =
    6.46 +  private val process =
    6.47      try {
    6.48        val cmdline =
    6.49          List(system.getenv_strict("ISABELLE_PROCESS"), "-W", in_fifo + ":" + out_fifo) ++ args
    6.50 -      system.execute(true, cmdline: _*)
    6.51 +      new system.Managed_Process(true, cmdline: _*)
    6.52      }
    6.53      catch { case e: IOException => rm_fifos(); throw(e) }
    6.54  
    6.55 -  private val stdout_reader =
    6.56 -    new BufferedReader(new InputStreamReader(proc.getInputStream, Standard_System.charset))
    6.57 +  private def terminate_process()
    6.58 +  {
    6.59 +    try { process.terminate }
    6.60 +    catch { case e: IOException => system_result("Failed to terminate Isabelle: " + e.getMessage) }
    6.61 +  }
    6.62  
    6.63 -  private val stdin_writer =
    6.64 -    new BufferedWriter(new OutputStreamWriter(proc.getOutputStream, Standard_System.charset))
    6.65 -
    6.66 -  private val (process_manager, _) = Simple_Thread.actor("process_manager")
    6.67 +  private val process_manager = Simple_Thread.fork("process_manager")
    6.68    {
    6.69      val (startup_failed, startup_output) =
    6.70      {
    6.71 @@ -152,8 +151,8 @@
    6.72  
    6.73        var finished = false
    6.74        while (!finished && System.currentTimeMillis() <= expired) {
    6.75 -        while (!finished && stdout_reader.ready) {
    6.76 -          val c = stdout_reader.read
    6.77 +        while (!finished && process.stdout.ready) {
    6.78 +          val c = process.stdout.read
    6.79            if (c == 2) finished = true
    6.80            else result += c.toChar
    6.81          }
    6.82 @@ -165,62 +164,45 @@
    6.83  
    6.84      if (startup_failed) {
    6.85        put_result(Markup.EXIT, "127")
    6.86 -      stdin_writer.close
    6.87 -      Thread.sleep(300)  // FIXME !?
    6.88 -      proc.destroy  // FIXME unreliable
    6.89 +      process.stdin.close
    6.90 +      Thread.sleep(300)
    6.91 +      terminate_process()
    6.92      }
    6.93      else {
    6.94        // rendezvous
    6.95        val command_stream = system.fifo_output_stream(in_fifo)
    6.96        val message_stream = system.fifo_input_stream(out_fifo)
    6.97  
    6.98 -      val stdin = stdin_actor(); standard_input = stdin._2
    6.99 +      standard_input = stdin_actor()
   6.100        val stdout = stdout_actor()
   6.101 -      val input = input_actor(command_stream); command_input = input._2
   6.102 +      command_input = input_actor(command_stream)
   6.103        val message = message_actor(message_stream)
   6.104  
   6.105 -      val rc = proc.waitFor()
   6.106 +      val rc = process.join
   6.107        system_result("Isabelle process terminated")
   6.108 -      for ((thread, _) <- List(stdin, stdout, input, message)) thread.join
   6.109 +      for ((thread, _) <- List(standard_input, stdout, command_input, message)) thread.join
   6.110        system_result("process_manager terminated")
   6.111        put_result(Markup.EXIT, rc.toString)
   6.112      }
   6.113      rm_fifos()
   6.114    }
   6.115  
   6.116 +
   6.117 +  /* management methods */
   6.118 +
   6.119    def join() { process_manager.join() }
   6.120  
   6.121 -
   6.122 -  /* signals */
   6.123 -
   6.124 -  @volatile private var pid: Option[String] = None
   6.125 -
   6.126    def interrupt()
   6.127    {
   6.128 -    pid match {
   6.129 -      case None => system_result("Cannot interrupt Isabelle: unknown pid")
   6.130 -      case Some(i) =>
   6.131 -        try {
   6.132 -          if (system.execute(true, "kill", "-INT", i).waitFor == 0)
   6.133 -            system_result("Interrupt Isabelle")
   6.134 -          else
   6.135 -            system_result("Cannot interrupt Isabelle: kill command failed")
   6.136 -        }
   6.137 -        catch { case e: IOException => error("Cannot interrupt Isabelle: " + e.getMessage) }
   6.138 -    }
   6.139 +    try { process.interrupt }
   6.140 +    catch { case e: IOException => system_result("Failed to interrupt Isabelle: " + e.getMessage) }
   6.141    }
   6.142  
   6.143 -  def kill()
   6.144 +  def terminate()
   6.145    {
   6.146 -    val running =
   6.147 -      try { proc.exitValue; false }
   6.148 -      catch { case e: java.lang.IllegalThreadStateException => true }
   6.149 -    if (running) {
   6.150 -      close()
   6.151 -      Thread.sleep(500)  // FIXME !?
   6.152 -      system_result("Kill Isabelle")
   6.153 -      proc.destroy
   6.154 -    }
   6.155 +    close()
   6.156 +    system_result("Terminating Isabelle process")
   6.157 +    terminate_process()
   6.158    }
   6.159  
   6.160  
   6.161 @@ -239,10 +221,10 @@
   6.162            //{{{
   6.163            receive {
   6.164              case Input_Text(text) =>
   6.165 -              stdin_writer.write(text)
   6.166 -              stdin_writer.flush
   6.167 +              process.stdin.write(text)
   6.168 +              process.stdin.flush
   6.169              case Close =>
   6.170 -              stdin_writer.close
   6.171 +              process.stdin.close
   6.172                finished = true
   6.173              case bad => System.err.println(name + ": ignoring bad message " + bad)
   6.174            }
   6.175 @@ -269,8 +251,8 @@
   6.176            //{{{
   6.177            var c = -1
   6.178            var done = false
   6.179 -          while (!done && (result.length == 0 || stdout_reader.ready)) {
   6.180 -            c = stdout_reader.read
   6.181 +          while (!done && (result.length == 0 || process.stdout.ready)) {
   6.182 +            c = process.stdout.read
   6.183              if (c >= 0) result.append(c.asInstanceOf[Char])
   6.184              else done = true
   6.185            }
   6.186 @@ -279,7 +261,7 @@
   6.187              result.length = 0
   6.188            }
   6.189            else {
   6.190 -            stdout_reader.close
   6.191 +            process.stdout.close
   6.192              finished = true
   6.193            }
   6.194            //}}}
   6.195 @@ -391,10 +373,10 @@
   6.196  
   6.197    /** main methods **/
   6.198  
   6.199 -  def input_raw(text: String): Unit = standard_input ! Input_Text(text)
   6.200 +  def input_raw(text: String): Unit = standard_input._2 ! Input_Text(text)
   6.201  
   6.202    def input_bytes(name: String, args: Array[Byte]*): Unit =
   6.203 -    command_input ! Input_Chunks(Standard_System.string_bytes(name) :: args.toList)
   6.204 +    command_input._2 ! Input_Chunks(Standard_System.string_bytes(name) :: args.toList)
   6.205  
   6.206    def input(name: String, args: String*): Unit =
   6.207      input_bytes(name, args.map(Standard_System.string_bytes): _*)
     7.1 --- a/src/Pure/System/session.scala	Wed Sep 22 12:52:35 2010 +0200
     7.2 +++ b/src/Pure/System/session.scala	Wed Sep 22 13:47:48 2010 +0200
     7.3 @@ -241,7 +241,7 @@
     7.4            Some(startup_error())
     7.5  
     7.6          case TIMEOUT =>  // FIXME clarify
     7.7 -          prover.kill; Some(startup_error())
     7.8 +          prover.terminate; Some(startup_error())
     7.9        }
    7.10      }
    7.11  
    7.12 @@ -282,7 +282,7 @@
    7.13          case Stop => // FIXME synchronous!?
    7.14            if (prover != null) {
    7.15              global_state.change(_ => Document.State.init)
    7.16 -            prover.kill
    7.17 +            prover.terminate
    7.18              prover = null
    7.19            }
    7.20