Subject: Clean up socket files set up by --listen=/path/to/socket-file

From: Christopher Allan Webber <[email-masked]>
Date: Sat, 29 Oct 2016 11:38:23 -0500

In light of the recent security vulnerability on using localhost + port,
I've been using socket files for live hacking.  Unfortunately, these
socket files stay around after closing guile, which means this can happen:

  $ guile --listen=/tmp/guile-socket
  scheme@(guile-user)> ,q
  $ guile --listen=/tmp/guile-socket
  ERROR: In procedure bind:
  ERROR: In procedure bind: Address already in use

That's not very nice!  I really don't like having to clean up these
files by hand.... Guile should do it for me.

Fortunately, here's a patch that does just that!  It uses dynamic-wind
and cleans up the socket file, if it exists.  (But it doesn't break if
it doesn't!)

From 12a1c24890448ec9a2d33cabff7f70f6332dbb4f Mon Sep 17 00:00:00 2001
From: Christopher Allan Webber <[email-masked]>
Date: Sat, 29 Oct 2016 11:28:05 -0500
Subject: [PATCH] Clean up socket file set up by --listen

* module/ice-9/command-line.scm (compile-shell-switches):
  Clean up socket file set up by --listen on exit, if it exists.
---
 module/ice-9/command-line.scm | 80 ++++++++++++++++++++++++-------------------
 1 file changed, 44 insertions(+), 36 deletions(-)

diff --git a/module/ice-9/command-line.scm b/module/ice-9/command-line.scm
index 98d3855..cdc5427 100644
--- a/module/ice-9/command-line.scm
+++ b/module/ice-9/command-line.scm
@@ -199,6 +199,7 @@ If FILE begins with `-' the -s switch is mandatory.
         (user-load-compiled-path '())
         (user-extensions '())
         (interactive? #t)
+        (clean-socket-file #f)
         (inhibit-user-init? #f)
         (turn-on-debugging? #f)
         (turn-off-debugging? #f))
@@ -387,6 +388,7 @@ If FILE begins with `-' the -s switch is mandatory.
                              ((@@ (system repl server) make-tcp-server-socket) #:port ,port))
                            (error "invalid port for --listen"))))
                  ((string-prefix? "/" where) ; --listen=/PATH/TO/SOCKET
+                  (set! clean-socket-file where)
                   `((@@ (system repl server) spawn-server)
                     ((@@ (system repl server) make-unix-domain-server-socket) #:path ,where)))
                  (else
@@ -430,42 +432,48 @@ If FILE begins with `-' the -s switch is mandatory.
       `(;; It would be nice not to load up (ice-9 control), but the
         ;; default-prompt-handler is nontrivial.
         (@ (ice-9 control) %)
-        (begin
-          ;; If we didn't end with a -c or a -s and didn't supply a -q, load
-          ;; the user's customization file.
-          ,@(if (and interactive? (not inhibit-user-init?))
-                '((load-user-init))
-                '())
-
-          ;; Use-specified extensions.
-          ,@(map (lambda (ext)
-                   `(set! %load-extensions (cons ,ext %load-extensions)))
-                 user-extensions)
-
-          ;; Add the user-specified load paths here, so they won't be in
-          ;; effect during the loading of the user's customization file.
-          ,@(map (lambda (path)
-                   `(set! %load-path (cons ,path %load-path)))
-                 user-load-path)
-          ,@(map (lambda (path)
-                   `(set! %load-compiled-path
-                          (cons ,path %load-compiled-path)))
-                 user-load-compiled-path)
-
-          ;; Put accumulated actions in their correct order.
-          ,@(reverse! out)
-
-          ;; Handle the `-e' switch, if it was specified.
-          ,@(if entry-point
-                `((,entry-point (command-line)))
-                '())
-          ,(if interactive?
-               ;; If we didn't end with a -c or a -s, start the
-               ;; repl.
-               '((@ (ice-9 top-repl) top-repl))
-               ;; Otherwise, after doing all the other actions
-               ;; prescribed by the command line, quit.
-               '(quit)))))
+        (dynamic-wind
+          (const #f) ; no-op
+          (lambda ()
+            ;; If we didn't end with a -c or a -s and didn't supply a -q, load
+            ;; the user's customization file.
+            ,@(if (and interactive? (not inhibit-user-init?))
+                  '((load-user-init))
+                  '())
+
+            ;; Use-specified extensions.
+            ,@(map (lambda (ext)
+                     `(set! %load-extensions (cons ,ext %load-extensions)))
+                   user-extensions)
+
+            ;; Add the user-specified load paths here, so they won't be in
+            ;; effect during the loading of the user's customization file.
+            ,@(map (lambda (path)
+                     `(set! %load-path (cons ,path %load-path)))
+                   user-load-path)
+            ,@(map (lambda (path)
+                     `(set! %load-compiled-path
+                            (cons ,path %load-compiled-path)))
+                   user-load-compiled-path)
+
+            ;; Put accumulated actions in their correct order.
+            ,@(reverse! out)
+
+            ;; Handle the `-e' switch, if it was specified.
+            ,@(if entry-point
+                  `((,entry-point (command-line)))
+                  '())
+            ,(if interactive?
+                 ;; If we didn't end with a -c or a -s, start the
+                 ;; repl.
+                 '((@ (ice-9 top-repl) top-repl))
+                 ;; Otherwise, after doing all the other actions
+                 ;; prescribed by the command line, quit.
+                 '(quit)))
+          (lambda ()
+            (when (and ,clean-socket-file
+                       (file-exists? ,clean-socket-file))
+              (delete-file ,clean-socket-file))))))
 
       (if (pair? args)
           (begin
-- 
2.10.1