About two weeks ago I asked on IRC whether there was support for using
SLIME via unix domains sockets.
Someone answererd in the negative, citing lack of unix domain socket
support on Emacs as the reason.
I later realized that this doesn't really matter, because we should be
able to use an arbitrary process object with a suitable external
command. I tried it, and it's working very nicely so far, using
unixclient path-to-socket ucspi-proxy
as a command in a process object on the Emacs side ("unixclient" and
"ucspi-proxy" are available in Debian in the ucspi-unix and
ucspi-proxy packages.)
(A side effect is that we can easily add other components into the
communications pipeline. Things I tried successfully:
recordio 2>/tmp/slime-io unixclient path-to-socket ucspi-proxy
to record communications, and
ssh remote-host unixclient path-to-socket ucspi-proxy
to use it from a remote machine.)
Below is what I hacked into swank.lisp in order to make unix domain
sockets work. Instead of adding specific code to create unix domain
sockets, I changed setup-server to accept a pre-established socket
object. This is a simple change that should allow anyone on a Lisp
that supports it to use unix domain sockets without much change to the
swank proper.
For the Emacs side, I don't have anything resembling useable patches
(being a total slime newbie, really). Something along the lines of the
above would probably be simplest, i.e. passing an established process
object for slime to use. Some necessary changes identified so far
seem to be:
* changing (eq (process-status conn) 'open) to (memq (process-status
conn) '(run open)) in a few places
* Avoid trying to get the "port" of a non-network process object.
I need to set (setf swank:*use-dedicated-output-stream* nil) to make
things work properly. Interaction looks to be fast enough, though.
Marcus
diff -u slime-1.0-original/swank.lisp slime-1.0/swank.lisp
--- slime-1.0-original/swank.lisp Sat Sep 4 18:19:52 2004
+++ slime-1.0/swank.lisp Sat Dec 18 14:09:36 2004
@@ -277,8 +277,10 @@
dont-close)
"Start the server and write the listen port number to PORT-FILE.
This is the entry point for Emacs."
- (setup-server 0 (lambda (port) (announce-server-port port-file port))
- style dont-close))
+ (create-swank-server 0 style
+ (lambda (port)
+ (announce-server-port port-file port))
+ dont-close))
(defun create-server (&key (port default-server-port)
(style *communication-style*)
@@ -286,37 +288,37 @@
"Start a SWANK server on PORT running in STYLE.
If DONT-CLOSE is true then the listen socket will accept multiple
connections, otherwise it will be closed after the first."
- (setup-server port #'simple-announce-function style dont-close))
+ (create-swank-server port style #'simple-announce-function dont-close))
(defun create-swank-server (&optional (port default-server-port)
(style *communication-style*)
(announce-fn #'simple-announce-function)
dont-close)
- (setup-server port announce-fn style dont-close))
-
-(defparameter *loopback-interface* "127.0.0.1")
-
-(defun setup-server (port announce-fn style dont-close)
- (declare (type function announce-fn))
(let* ((socket (create-socket *loopback-interface* port))
(port (local-port socket)))
(funcall announce-fn port)
- (ecase style
- (:spawn
- (spawn (lambda ()
- (loop do (serve-connection socket :spawn dont-close)
- while dont-close))
- :name "Swank"))
- ((:fd-handler :sigio)
- (add-fd-handler socket
- (lambda ()
- (serve-connection socket style dont-close))))
- ((nil)
- (unwind-protect
- (loop do (serve-connection socket style dont-close)
- while dont-close)
- (close-socket socket))))
+ (setup-server socket style dont-close)
port))
+
+(defparameter *loopback-interface* "127.0.0.1")
+
+(defun setup-server (socket style dont-close)
+ (declare (type function announce-fn))
+ (ecase style
+ (:spawn
+ (spawn (lambda ()
+ (loop do (serve-connection socket :spawn dont-close)
+ while dont-close))
+ :name "Swank"))
+ ((:fd-handler :sigio)
+ (add-fd-handler socket
+ (lambda ()
+ (serve-connection socket style dont-close))))
+ ((nil)
+ (unwind-protect
+ (loop do (serve-connection socket style dont-close)
+ while dont-close)
+ (close-socket socket)))))
(defun serve-connection (socket style dont-close)
(let ((client (accept-connection socket)))