]> git.eshelyaron.com Git - dict.git/commitdiff
Start the top-level TCP server just-in-time
authorEshel Yaron <me@eshelyaron.com>
Tue, 15 Nov 2022 21:45:02 +0000 (23:45 +0200)
committerEshel Yaron <me@eshelyaron.com>
Tue, 15 Nov 2022 21:48:39 +0000 (23:48 +0200)
* sweeprolog.el (sweeprolog-init): do not start TCP server
unconditionally
(sweeprolog-top-level): start it here instead, on demand.
* sweep.pl (sweep_top_level_server/2): wait for TCP server thread to
start before returning control to Emacs.
* README.org (The Prolog Top-Level): add implementation note.

README.org
sweep.pl
sweeprolog.el

index 0f1c212c1e27bfcf5672c96577520e2e7c6f4b61..62aa707f28582adfa355effdc0ad2af886e504b3 100644 (file)
@@ -1107,7 +1107,7 @@ definition or invocation in a ~sweeprolog-mode~, that predicate is set
 as the default selection and can be described by simply typing ~RET~ in
 response to the prompt.
 
-* The Prolog top-level
+* The Prolog Top-Level
 :PROPERTIES:
 :CUSTOM_ID: prolog-top-level
 :DESCRIPTION: Executing Prolog queries in a REPL-like interface
@@ -1128,6 +1128,19 @@ common mode used in Emacs REPL interfaces.  As a result, the top-level
 buffer inherits the features present in other =comint-mode= derivatives,
 most of which are described in [[info:emacs#Shell Mode][the Emacs manual]].
 
+Each top-level buffer is connected to distinct Prolog thread running
+in the same process as Emacs and the main Prolog runtime.  In the
+current implementation, top-level buffers communicate with their
+corresponding threads via local TCP connections.  On the first
+invocation of ~sweeprolog-top-level~, ~sweep~ creates a TCP server socket
+bound to a random port to accept incoming connections from top-level
+buffers.  The TCP server only accepts connections from the local
+machine, but note that _other users on the same host_ may be able to
+connect to the TCP server socket and _get a Prolog top-level_.  This may
+pose a security problem when sharing a host with entrusted users,
+hence ~sweeprolog-top-level~ _should not be used on shared machines_.
+This is the only ~sweep~ feature that should be avoided in such cases.
+
 ** Multiple top-levels
 :PROPERTIES:
 :CUSTOM_ID: multiple-top-levels
index 233c7efaf39bd8560c19f42150ff804fffeb67c7..7d1032efaff75992c32eb95fd111ff54c1c1b957 100644 (file)
--- a/sweep.pl
+++ b/sweep.pl
@@ -607,7 +607,8 @@ sweep_top_level_server(_, Port) :-
     tcp_setopt(ServerSocket, reuseaddr),
     tcp_bind(ServerSocket, Port),
     tcp_listen(ServerSocket, 5),
-    thread_create(sweep_top_level_server_loop(ServerSocket), T,
+    thread_self(Self),
+    thread_create(sweep_top_level_server_start(Self, ServerSocket), T,
                   [ alias(sweep_top_level_server)
                   ]),
     at_halt((   is_thread(T),
@@ -615,7 +616,12 @@ sweep_top_level_server(_, Port) :-
             ->  thread_signal(T, thread_exit(0)),
                 thread_join(T, _)
             ;   true
-            )).
+            )),
+    thread_get_message(sweep_top_level_server_started).
+
+sweep_top_level_server_start(Caller, ServerSocket) :-
+    thread_send_message(Caller, sweep_top_level_server_started),
+    sweep_top_level_server_loop(ServerSocket).
 
 sweep_top_level_server_loop(ServerSocket) :-
     thread_get_message(Message),
index bc4a46f69e04fea9336eb8e57be8aa5a91b68cc1..87dfcc33b3478ff9ba1c4bb078485e68a90ef4c5 100644 (file)
@@ -524,8 +524,7 @@ extra initialization arguments."
            (cons (or sweeprolog-swipl-path (executable-find "swipl"))
                  (append sweeprolog-init-args args)))
     (setq sweeprolog--initialized t)
-    (sweeprolog-setup-message-hook)
-    (sweeprolog-start-prolog-server)))
+    (sweeprolog-setup-message-hook)))
 
 (defun sweeprolog-restart (&rest args)
   "Restart the embedded Prolog runtime.
@@ -2222,6 +2221,8 @@ Interactively, a prefix arg means to prompt for BUFFER."
     (with-current-buffer buf
       (unless (eq major-mode 'sweeprolog-top-level-mode)
         (sweeprolog-top-level-mode)))
+    (unless sweeprolog-prolog-server-port
+      (sweeprolog-start-prolog-server))
     (unless (sweeprolog--query-once "sweep" "sweep_accept_top_level_client"
                                     (buffer-name buf))
       (error "Failed to create new top-level!"))