Add a restart for ports already in use
author |
Steve Losh <steve@stevelosh.com> |
date |
Tue, 14 Mar 2017 17:46:14 +0000 |
parents |
eee835835b39
|
children |
(none) |
branches/tags |
default tip |
files |
src/server.lisp |
Changes
--- a/src/server.lisp Tue Mar 14 13:33:00 2017 +0000
+++ b/src/server.lisp Tue Mar 14 17:46:14 2017 +0000
@@ -66,6 +66,12 @@
;;;; Server
(defvar *server-thread* nil)
+(define-condition port-error (error)
+ ((port :initarg :port))
+ (:report (lambda (err stream)
+ (format stream "Port ~D is already in use"
+ (slot-value err 'port)))))
+
(defmacro run-in-thread (thread-name &rest body)
"Run `body` in a thread called `name` (usually). Return the thread.
@@ -78,6 +84,26 @@
(progn (funcall thunk) nil)
(bt:make-thread thunk :name ,thread-name))))
+(defun socket-listen (address port)
+ (handler-case
+ (values (usocket:socket-listen
+ address port
+ :reuse-address t
+ ;; have to specify element-type here too because usocket+CCL
+ ;; fucks it up if you only specify it in socket-accept
+ :element-type '(unsigned-byte 8))
+ port)
+ (usocket:address-in-use-error ()
+ (restart-case (error 'port-error :port port)
+ (use-different-port (new-port)
+ :report (lambda (stream)
+ (format stream "Select a port other than ~D" port))
+ :interactive (lambda ()
+ (format *query-io* "~&Type a form to be evaluated:~%")
+ (finish-output *query-io*)
+ (list (read *query-io*)))
+ (socket-listen address new-port))))))
+
(defun accept-connections (server-socket)
"Accept connections to the server and spawn threads to handle each."
@@ -98,12 +124,7 @@
(defun start-server (&key (address "127.0.0.1") (port 8675))
"Fire up a server thread that will listen for connections."
(log-message "Starting server...~%")
- (let ((socket (usocket:socket-listen
- address port
- :reuse-address t
- ;; have to specify element-type here too because usocket+CCL
- ;; fucks it up if you only specify it in socket-accept
- :element-type '(unsigned-byte 8))))
+ (multiple-value-bind (socket port) (socket-listen address port)
(setf *server-thread*
(run-in-thread (format nil "NREPL Server (~a/~a)" address port)
(unwind-protect