added Isabelle_Process.syslog;
authorwenzelm
Mon, 20 Sep 2010 21:20:06 +0200
changeset 39572 bb3469024b6a
parent 39571 3a3d9de2ad6e
child 39573 a874ca3f5474
added Isabelle_Process.syslog; refined Isabelle_Process.process_manager: startup_output via syslog, explicit join of auxiliary threads; tuned;
src/Pure/Concurrent/simple_thread.scala
src/Pure/System/isabelle_process.scala
src/Pure/System/session.scala
--- a/src/Pure/Concurrent/simple_thread.scala	Mon Sep 20 19:00:47 2010 +0200
+++ b/src/Pure/Concurrent/simple_thread.scala	Mon Sep 20 21:20:06 2010 +0200
@@ -27,11 +27,11 @@
 
   /* thread as actor */
 
-  def actor(name: String, daemon: Boolean = false)(body: => Unit): Actor =
+  def actor(name: String, daemon: Boolean = false)(body: => Unit): (Thread, Actor) =
   {
     val actor = Future.promise[Actor]
     val thread = fork(name, daemon) { actor.fulfill(Actor.self); body }
-    actor.join
+    (thread, actor.join)
   }
 }
 
--- a/src/Pure/System/isabelle_process.scala	Mon Sep 20 19:00:47 2010 +0200
+++ b/src/Pure/System/isabelle_process.scala	Mon Sep 20 21:20:06 2010 +0200
@@ -13,6 +13,7 @@
 
 import scala.actors.Actor
 import Actor._
+import scala.collection.mutable
 
 
 object Isabelle_Process
@@ -104,7 +105,8 @@
   private val stdin_writer =
     new BufferedWriter(new OutputStreamWriter(proc.getOutputStream, Standard_System.charset))
 
-  Simple_Thread.actor("process_manager") {
+  private val (process_manager, _) = Simple_Thread.actor("process_manager")
+  {
     val (startup_failed, startup_output) =
     {
       val expired = System.currentTimeMillis() + timeout
@@ -121,42 +123,50 @@
       }
       (!finished, result.toString)
     }
+    system_result(startup_output)
+
     if (startup_failed) {
-      put_result(Markup.STDOUT, startup_output)
       put_result(Markup.EXIT, "127")
       stdin_writer.close
       Thread.sleep(300)  // FIXME !?
-      proc.destroy  // FIXME reliable!?
+      proc.destroy  // FIXME unreliable
     }
     else {
-      put_result(Markup.SYSTEM, startup_output)
-
-      standard_input = stdin_actor()
-      stdout_actor()
-
       // rendezvous
       val command_stream = system.fifo_output_stream(in_fifo)
       val message_stream = system.fifo_input_stream(out_fifo)
 
-      command_input = input_actor(command_stream)
-      message_actor(message_stream)
+      val stdin = stdin_actor(); standard_input = stdin._2
+      val stdout = stdout_actor()
+      val input = input_actor(command_stream); command_input = input._2
+      val message = message_actor(message_stream)
 
       val rc = proc.waitFor()
-      Thread.sleep(300)  // FIXME !?
       system_result("Isabelle process terminated")
+      for ((thread, _) <- List(stdin, stdout, input, message)) thread.join
+      system_result("process_manager terminated")
       put_result(Markup.EXIT, rc.toString)
     }
     rm_fifos()
   }
 
+  def join() { process_manager.join() }
 
-  /* results */
+
+  /* system log */
+
+  private val system_results = new mutable.ListBuffer[String]
 
   private def system_result(text: String)
   {
+    synchronized { system_results += text }
     receiver ! new Result(XML.Elem(Markup(Markup.SYSTEM, Nil), List(XML.Text(text))))
   }
 
+  def syslog(): List[String] = synchronized { system_results.toList }
+
+
+  /* results */
 
   private val xml_cache = new XML.Cache(131071)
 
@@ -219,7 +229,7 @@
 
   /* raw stdin */
 
-  private def stdin_actor(): Actor =
+  private def stdin_actor(): (Thread, Actor) =
   {
     val name = "standard_input"
     Simple_Thread.actor(name) {
@@ -247,7 +257,7 @@
 
   /* raw stdout */
 
-  private def stdout_actor(): Actor =
+  private def stdout_actor(): (Thread, Actor) =
   {
     val name = "standard_output"
     Simple_Thread.actor(name) {
@@ -283,7 +293,7 @@
 
   /* command input */
 
-  private def input_actor(raw_stream: OutputStream): Actor =
+  private def input_actor(raw_stream: OutputStream): (Thread, Actor) =
   {
     val name = "command_input"
     Simple_Thread.actor(name) {
@@ -314,7 +324,7 @@
 
   /* message output */
 
-  private def message_actor(stream: InputStream): Actor =
+  private def message_actor(stream: InputStream): (Thread, Actor) =
   {
     class EOF extends Exception
     class Protocol_Error(msg: String) extends Exception(msg)
--- a/src/Pure/System/session.scala	Mon Sep 20 19:00:47 2010 +0200
+++ b/src/Pure/System/session.scala	Mon Sep 20 21:20:06 2010 +0200
@@ -63,7 +63,8 @@
 
   private case object Stop
 
-  private val command_change_buffer = Simple_Thread.actor("command_change_buffer", daemon = true)
+  private val (_, command_change_buffer) =
+    Simple_Thread.actor("command_change_buffer", daemon = true)
   //{{{
   {
     import scala.compat.Platform.currentTime
@@ -118,7 +119,7 @@
   private case class Edit_Version(edits: List[Document.Node_Text_Edit])
   private case class Started(timeout: Int, args: List[String])
 
-  private val session_actor = Simple_Thread.actor("session_actor", daemon = true)
+  private val (_, session_actor) = Simple_Thread.actor("session_actor", daemon = true)
   {
     var prover: Isabelle_Process with Isar_Document = null
 
@@ -202,7 +203,7 @@
           }
           else if (result.is_exit) prover = null  // FIXME ??
           else if (result.is_stdout) raw_output.event(result)
-          else if (!result.is_system) bad_result(result)  // FIXME syslog for system messages (!?)
+          else if (!result.is_system) bad_result(result)
         }
     }
     //}}}
@@ -216,7 +217,7 @@
       while (
         receiveWithin(0) {
           case result: Isabelle_Process.Result =>
-            if (result.is_stdout) {
+            if (result.is_system) {
               for (text <- XML.content(result.message))
                 buf.append(text)
             }
@@ -272,7 +273,7 @@
           if (prover == null) {
             prover = new Isabelle_Process(system, timeout, self, args:_*) with Isar_Document
             val origin = sender
-            val opt_err = prover_startup(timeout)
+            val opt_err = prover_startup(timeout + 500)
             if (opt_err.isDefined) prover = null
             origin ! opt_err
           }