discontinued fifo channel, always use portable socket;
authorwenzelm
Sun, 11 Jan 2015 20:40:14 +0100
changeset 59350 acba5d6fdb2f
parent 59349 3bde948f439c
child 59351 bb6eecfd7a55
discontinued fifo channel, always use portable socket;
bin/isabelle_process
src/Doc/System/Basics.thy
src/Pure/System/isabelle_process.ML
src/Pure/System/system_channel.ML
src/Pure/System/system_channel.scala
--- a/bin/isabelle_process	Sun Jan 11 13:44:25 2015 +0100
+++ b/bin/isabelle_process	Sun Jan 11 20:40:14 2015 +0100
@@ -27,9 +27,8 @@
   echo
   echo "  Options are:"
   echo "    -O           system options from given YXML file"
+  echo "    -P SOCKET    startup process wrapper via TCP socket"
   echo "    -S           secure mode -- disallow critical operations"
-  echo "    -T ADDR      startup process wrapper, with socket address"
-  echo "    -W IN:OUT    startup process wrapper, with input/output fifos"
   echo "    -e MLTEXT    pass MLTEXT to the ML session"
   echo "    -m MODE      add print mode for output"
   echo "    -o OPTION    override Isabelle system OPTION (via NAME=VAL or NAME)"
@@ -57,9 +56,8 @@
 # options
 
 OPTIONS_FILE=""
+PROCESS_SOCKET=""
 SECURE=""
-WRAPPER_SOCKET=""
-WRAPPER_FIFOS=""
 MLTEXT=""
 MODES=""
 declare -a SYSTEM_OPTIONS=()
@@ -67,21 +65,18 @@
 READONLY=""
 NOWRITE=""
 
-while getopts "O:ST:W:e:m:o:qrw" OPT
+while getopts "O:P:Se:m:o:qrw" OPT
 do
   case "$OPT" in
     O)
       OPTIONS_FILE="$OPTARG"
       ;;
+    P)
+      PROCESS_SOCKET="$OPTARG"
+      ;;
     S)
       SECURE=true
       ;;
-    T)
-      WRAPPER_SOCKET="$OPTARG"
-      ;;
-    W)
-      WRAPPER_FIFOS="$OPTARG"
-      ;;
     e)
       MLTEXT="$MLTEXT $OPTARG"
       ;;
@@ -203,14 +198,8 @@
 
 [ -n "$SECURE" ] && MLTEXT="$MLTEXT; Secure.set_secure ();"
 
-if [ -n "$WRAPPER_SOCKET" ]; then
-  MLTEXT="$MLTEXT; Isabelle_Process.init_socket \"$WRAPPER_SOCKET\";"
-elif [ -n "$WRAPPER_FIFOS" ]; then
-  splitarray ":" "$WRAPPER_FIFOS"; FIFOS=("${SPLITARRAY[@]}")
-  [ "${#FIFOS[@]}" -eq 2 ] || fail "Expected IN:OUT fifo specification"
-  [ -p "${FIFOS[0]}" ] || fail "Bad input fifo: ${FIFOS[0]}"
-  [ -p "${FIFOS[1]}" ] || fail "Bad output fifo: ${FIFOS[1]}"
-  MLTEXT="$MLTEXT; Isabelle_Process.init_fifos \"${FIFOS[0]}\" \"${FIFOS[1]}\";"
+if [ -n "$PROCESS_SOCKET" ]; then
+  MLTEXT="$MLTEXT; Isabelle_Process.init \"$PROCESS_SOCKET\";"
 else
   ISABELLE_PROCESS_OPTIONS="$ISABELLE_TMP/options"
   if [ -n "$OPTIONS_FILE" ]; then
--- a/src/Doc/System/Basics.thy	Sun Jan 11 13:44:25 2015 +0100
+++ b/src/Doc/System/Basics.thy	Sun Jan 11 20:40:14 2015 +0100
@@ -362,9 +362,8 @@
 
   Options are:
     -O           system options from given YXML file
+    -P SOCKET    startup process wrapper via TCP socket
     -S           secure mode -- disallow critical operations
-    -T ADDR      startup process wrapper, with socket address
-    -W IN:OUT    startup process wrapper, with input/output fifos
     -e MLTEXT    pass MLTEXT to the ML session
     -m MODE      add print mode for output
     -o OPTION    override Isabelle system OPTION (via NAME=VAL or NAME)
@@ -433,11 +432,11 @@
   system options as a file in YXML format (according to the Isabelle/Scala
   function @{verbatim isabelle.Options.encode}).
 
-  \medskip The @{verbatim "-T"} or @{verbatim "-W"} option makes
-  Isabelle enter a special process wrapper for interaction via
-  Isabelle/Scala, see also @{file
-  "~~/src/Pure/System/isabelle_process.scala"}.  The protocol between
-  the ML and JVM process is private to the implementation.
+  \medskip The @{verbatim "-P"} option starts the Isabelle process wrapper
+  for Isabelle/Scala, with a private protocol running over the specified TCP
+  socket. Isabelle/ML and Isabelle/Scala provide various programming
+  interfaces to invoke protocol functions over untyped strings and XML
+  trees.
 
   \medskip The @{verbatim "-S"} option makes the Isabelle process more
   secure by disabling some critical operations, notably runtime
--- a/src/Pure/System/isabelle_process.ML	Sun Jan 11 13:44:25 2015 +0100
+++ b/src/Pure/System/isabelle_process.ML	Sun Jan 11 20:40:14 2015 +0100
@@ -10,8 +10,7 @@
   val protocol_command: string -> (string list -> unit) -> unit
   val reset_tracing: Document_ID.exec -> unit
   val crashes: exn list Synchronized.var
-  val init_fifos: string -> string -> unit
-  val init_socket: string -> unit
+  val init: string -> unit
 end;
 
 structure Isabelle_Process: ISABELLE_PROCESS =
@@ -189,7 +188,7 @@
 val default_modes1 = [Syntax_Trans.no_bracketsN, Syntax_Trans.no_type_bracketsN];
 val default_modes2 = [Symbol.xsymbolsN, isabelle_processN, Pretty.symbolicN];
 
-val init = uninterruptible (fn _ => fn rendezvous =>
+val init = uninterruptible (fn _ => fn socket =>
   let
     val _ = SHA1_Samples.test ()
       handle exn as Fail msg => (Output.physical_stderr (msg ^ "\n"); reraise exn);
@@ -201,14 +200,11 @@
       Unsynchronized.change print_mode
         (fn mode => (mode @ default_modes1) |> fold (update op =) default_modes2);
 
-    val channel = rendezvous ();
+    val channel = System_Channel.rendezvous socket;
     val msg_channel = init_channels channel;
     val _ = Session.init_protocol_handlers ();
     val _ = loop channel;
   in Message_Channel.shutdown msg_channel end);
 
-fun init_fifos fifo1 fifo2 = init (fn () => System_Channel.fifo_rendezvous fifo1 fifo2);
-fun init_socket name = init (fn () => System_Channel.socket_rendezvous name);
-
 end;
 
--- a/src/Pure/System/system_channel.ML	Sun Jan 11 13:44:25 2015 +0100
+++ b/src/Pure/System/system_channel.ML	Sun Jan 11 20:40:14 2015 +0100
@@ -1,8 +1,7 @@
 (*  Title:      Pure/System/system_channel.ML
     Author:     Makarius
 
-Portable system channel for inter-process communication, based on
-named pipes or sockets.
+Socket-based system channel for inter-process communication.
 *)
 
 signature SYSTEM_CHANNEL =
@@ -12,44 +11,15 @@
   val inputN: T -> int -> string
   val output: T -> string -> unit
   val flush: T -> unit
-  val fifo_rendezvous: string -> string -> T
-  val socket_rendezvous: string -> T
+  val rendezvous: string -> T
 end;
 
 structure System_Channel: SYSTEM_CHANNEL =
 struct
 
-datatype T = System_Channel of
- {input_line: unit -> string option,
-  inputN: int -> string,
-  output: string -> unit,
-  flush: unit -> unit};
-
-fun input_line (System_Channel {input_line = f, ...}) = f ();
-fun inputN (System_Channel {inputN = f, ...}) n = f n;
-fun output (System_Channel {output = f, ...}) s = f s;
-fun flush (System_Channel {flush = f, ...}) = f ();
-
-
-(* named pipes *)
+datatype T = System_Channel of BinIO.instream * BinIO.outstream;
 
-fun fifo_rendezvous fifo1 fifo2 =
-  let
-    val in_stream = TextIO.openIn fifo1;
-    val out_stream = TextIO.openOut fifo2;
-    val _ = TextIO.StreamIO.setBufferMode (TextIO.getOutstream out_stream, IO.BLOCK_BUF);
-  in
-    System_Channel
-     {input_line = fn () => TextIO.inputLine in_stream,
-      inputN = fn n => TextIO.inputN (in_stream, n),
-      output = fn s => TextIO.output (out_stream, s),
-      flush = fn () => TextIO.flushOut out_stream}
-  end;
-
-
-(* sockets *)
-
-fun read_line in_stream =
+fun input_line (System_Channel (in_stream, _)) =
   let
     fun result cs = String.implode (rev (#"\n" :: cs));
     fun read cs =
@@ -61,19 +31,21 @@
           | c => read (c :: cs)));
   in read [] end;
 
-fun socket_rendezvous name =
+fun inputN (System_Channel (in_stream, _)) n =
+  if n = 0 then ""  (*workaround for polyml-5.5.1 or earlier*)
+  else Byte.bytesToString (BinIO.inputN (in_stream, n));
+
+fun output (System_Channel (_, out_stream)) s =
+  BinIO.output (out_stream, Byte.stringToBytes s);
+
+fun flush (System_Channel (_, out_stream)) =
+  BinIO.flushOut out_stream;
+
+fun rendezvous name =
   let
     val (in_stream, out_stream) = Socket_IO.open_streams name;
     val _ = BinIO.StreamIO.setBufferMode (BinIO.getOutstream out_stream, IO.BLOCK_BUF);
-  in
-    System_Channel
-     {input_line = fn () => read_line in_stream,
-      inputN = fn n =>
-        if n = 0 then ""  (*workaround for polyml-5.5.1 or earlier*)
-        else Byte.bytesToString (BinIO.inputN (in_stream, n)),
-      output = fn s => BinIO.output (out_stream, Byte.stringToBytes s),
-      flush = fn () => BinIO.flushOut out_stream}
-  end;
+  in System_Channel (in_stream, out_stream) end;
 
 end;
 
--- a/src/Pure/System/system_channel.scala	Sun Jan 11 13:44:25 2015 +0100
+++ b/src/Pure/System/system_channel.scala	Sun Jan 11 20:40:14 2015 +0100
@@ -1,87 +1,28 @@
 /*  Title:      Pure/System/system_channel.scala
     Author:     Makarius
 
-Portable system channel for inter-process communication, based on
-named pipes or sockets.
+Socket-based system channel for inter-process communication.
 */
 
 package isabelle
 
 
-import java.io.{InputStream, OutputStream, File => JFile, FileInputStream,
-  FileOutputStream, IOException}
+import java.io.{InputStream, OutputStream}
 import java.net.{ServerSocket, InetAddress}
 
 
 object System_Channel
 {
-  def apply(): System_Channel = new Socket_Channel
-    // FIXME if (Platform.is_windows) new Socket_Channel else new Fifo_Channel
-}
-
-abstract class System_Channel
-{
-  def params: List[String]
-  def prover_args: List[String]
-  def rendezvous(): (OutputStream, InputStream)
-  def accepted(): Unit
-}
-
-
-/** named pipes **/
-
-private object Fifo_Channel
-{
-  private val next_fifo = Counter.make()
+  def apply(): System_Channel = new System_Channel
 }
 
-private class Fifo_Channel extends System_Channel
-{
-  require(!Platform.is_windows)
-
-  private def mk_fifo(): String =
-  {
-    val i = Fifo_Channel.next_fifo()
-    val script =
-      "FIFO=\"${TMPDIR:-/tmp}/isabelle-fifo-${PPID}-$$" + i + "\"\n" +
-      "echo -n \"$FIFO\"\n" +
-      "mkfifo -m 600 \"$FIFO\"\n"
-    val result = Isabelle_System.bash(script)
-    if (result.rc == 0) result.out else error(result.err)
-  }
-
-  private def rm_fifo(fifo: String): Boolean = (new JFile(fifo)).delete
-
-  private def fifo_input_stream(fifo: String): InputStream = new FileInputStream(fifo)
-  private def fifo_output_stream(fifo: String): OutputStream = new FileOutputStream(fifo)
-
-  private val fifo1 = mk_fifo()
-  private val fifo2 = mk_fifo()
-
-  def params: List[String] = List(fifo1, fifo2)
-
-  val prover_args: List[String] = List ("-W", fifo1 + ":" + fifo2)
-
-  def rendezvous(): (OutputStream, InputStream) =
-  {
-    val output_stream = fifo_output_stream(fifo1)
-    val input_stream = fifo_input_stream(fifo2)
-    (output_stream, input_stream)
-  }
-
-  def accepted() { rm_fifo(fifo1); rm_fifo(fifo2) }
-}
-
-
-/** sockets **/
-
-private class Socket_Channel extends System_Channel
+class System_Channel private
 {
   private val server = new ServerSocket(0, 2, InetAddress.getByName("127.0.0.1"))
 
   def params: List[String] = List("127.0.0.1", server.getLocalPort.toString)
 
-  def prover_args: List[String] = List("-T", "127.0.0.1:" + server.getLocalPort)
+  def prover_args: List[String] = List("-P", "127.0.0.1:" + server.getLocalPort)
 
   def rendezvous(): (OutputStream, InputStream) =
   {