--- 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) =
{