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
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
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),
-> 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),
(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.
(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!"))