refined Isabelle_System.bash_output: pass pid via stdout, separate stdout/stderr;
authorwenzelm
Tue, 21 Sep 2010 22:16:22 +0200
changeset 39581 430ff865089b
parent 39580 05daab5782f6
child 39582 a873158542d0
refined Isabelle_System.bash_output: pass pid via stdout, separate stdout/stderr;
lib/scripts/process
src/Pure/System/isabelle_system.scala
--- a/lib/scripts/process	Tue Sep 21 22:08:13 2010 +0200
+++ b/lib/scripts/process	Tue Sep 21 22:16:22 2010 +0200
@@ -23,12 +23,17 @@
 
 # pid
 
-open (PID_FILE, ">", $pid_name) || die $!;
-print PID_FILE "$$";
-close PID_FILE;
+if ($pid_name eq "-") {
+  print "$$\n";
+}
+else {
+  open (PID_FILE, ">", $pid_name) || die $!;
+  print PID_FILE "$$";
+  close PID_FILE;
+}
 
 
 # exec process
 
-exec "$cmd_line";
+exec $cmd_line;
 
--- a/src/Pure/System/isabelle_system.scala	Tue Sep 21 22:08:13 2010 +0200
+++ b/src/Pure/System/isabelle_system.scala	Tue Sep 21 22:16:22 2010 +0200
@@ -197,72 +197,60 @@
 
   /** system tools **/
 
-  def bash_output(script: String): (String, Int) =
+  def bash(script: String): (String, String, Int) =
   {
     Standard_System.with_tmp_file("isabelle_script") { script_file =>
-      Standard_System.with_tmp_file("isabelle_pid") { pid_file =>
+      Standard_System.write_file(script_file, script)
 
-        Standard_System.write_file(script_file, script)
-
-        val proc = execute(true, expand_path("$ISABELLE_HOME/lib/scripts/process"), "group",
-          posix_path(pid_file.getPath), "exec bash " + posix_path(script_file.getPath))
+      val proc =
+        execute(false, expand_path("$ISABELLE_HOME/lib/scripts/process"), "group", "-",
+          "exec bash " + posix_path(script_file.getPath))
 
-        val stdout = new StringBuilder(100)
-        val stdout_thread = Simple_Thread.fork("stdout")
-        {
-          val reader =
-            new BufferedReader(new InputStreamReader(proc.getInputStream, Standard_System.charset))
-          var c = -1
-          while ({ c = reader.read; c != -1 }) stdout += c.asInstanceOf[Char]
-          reader.close
-        }
+      val stdout_reader =
+        new BufferedReader(new InputStreamReader(proc.getInputStream, Standard_System.charset))
+
+      val stderr_reader =
+        new BufferedReader(new InputStreamReader(proc.getErrorStream, Standard_System.charset))
 
-        def kill(strict: Boolean) =
-        {
-          val pid =
-            try { Some(Standard_System.read_file(pid_file)) }
-            catch { case _: IOException => None }
-          if (pid.isDefined) {
-            var running = true
-            var count = 10   // FIXME property!?
-            while (running && count > 0) {
-              if (execute(true, "kill", "-INT", "-" + pid.get).waitFor != 0)
-                running = false
-              else {
-                Thread.sleep(100)   // FIXME property!?
-                if (!strict) count -= 1
-              }
-            }
+      val pid = stdout_reader.readLine
+
+      def kill(strict: Boolean) =
+      {
+        var running = true
+        var count = 10   // FIXME property!?
+        while (running && count > 0) {
+          if (execute(true, "kill", "-INT", "-" + pid).waitFor != 0)
+            running = false
+          else {
+            Thread.sleep(100)   // FIXME property!?
+            if (!strict) count -= 1
           }
         }
+      }
 
-        val shutdown_hook = new Thread { override def run = kill(true) }
-        Runtime.getRuntime.addShutdownHook(shutdown_hook)  // FIXME tmp files during shutdown?!?
+      val shutdown_hook = new Thread { override def run = kill(true) }
+      Runtime.getRuntime.addShutdownHook(shutdown_hook)  // FIXME tmp file during shutdown?!?
 
-        def cleanup() =
-          try { Runtime.getRuntime.removeShutdownHook(shutdown_hook) }
-          catch { case _: IllegalStateException => }
+      def cleanup() =
+        try { Runtime.getRuntime.removeShutdownHook(shutdown_hook) }
+        catch { case _: IllegalStateException => }
+
+      val stdout = Simple_Thread.future { Standard_System.slurp(stdout_reader) }
+      val stderr = Simple_Thread.future { Standard_System.slurp(stderr_reader) }
+      proc.getOutputStream.close
 
-        val rc =
-          try {
-            try {
-              val rc = proc.waitFor  // FIXME read stderr (!??)
-              stdout_thread.join
-              rc
-            }
-            catch { case e: InterruptedException => Thread.interrupted; kill(false); throw e }
-          }
-          finally {
-            proc.getOutputStream.close
-            proc.getInputStream.close
-            proc.getErrorStream.close
-            proc.destroy
-            cleanup()
-          }
-
-        stdout_thread.join()
-        (stdout.toString, rc)
-      }
+      val rc =
+        try {
+          try { proc.waitFor }
+          catch { case e: InterruptedException => Thread.interrupted; kill(false); 2 }
+        }
+        finally {
+          stdout.join
+          stderr.join
+          proc.destroy  // FIXME kill -TERM !?
+          cleanup()
+        }
+      (stdout.join, stderr.join, rc)
     }
   }
 
@@ -297,9 +285,8 @@
       "FIFO=\"/tmp/isabelle-fifo-${PPID}-$$-" + i + "\"\n" +
       "mkfifo -m 600 \"$FIFO\" || { echo \"Failed to create fifo: $FIFO\" >&2; exit 2; }\n" +
       "echo -n \"$FIFO\"\n"
-    val (result, rc) = bash_output(script)
-    if (rc == 0) result
-    else error(result)
+    val (out, err, rc) = bash(script)
+    if (rc == 0) out else error(err)
   }
 
   def rm_fifo(fifo: String): Boolean =