+25
-3
@@ -1,7 +1,8 @@
|
||||
(ns tbd.nrepl.core
|
||||
"The on-demand nREPL debug server. No HTTP here."
|
||||
(:require [clojure.string :as str]
|
||||
[nrepl.server :as nrepl]))
|
||||
[nrepl.server :as nrepl])
|
||||
(:import (java.net InetAddress InetSocketAddress Socket)))
|
||||
|
||||
(def default-port 7888)
|
||||
|
||||
@@ -35,11 +36,32 @@
|
||||
(reset! state {:server server :bind bind :port (:port server)})))
|
||||
(status)))
|
||||
|
||||
(defn- accepting?
|
||||
"True if something takes connections on `bind`:`port` (a wildcard bind is probed via loopback)."
|
||||
[bind port]
|
||||
(let [addr (InetAddress/getByName bind)
|
||||
addr (if (.isAnyLocalAddress addr) (InetAddress/getLoopbackAddress) addr)]
|
||||
(try (with-open [s (Socket.)]
|
||||
(.connect s (InetSocketAddress. addr (int port)) 200)
|
||||
true)
|
||||
(catch java.io.IOException _ false))))
|
||||
|
||||
(defn- await-closed
|
||||
"Blocks until `bind`:`port` refuses connections, for up to two seconds. Closing a server socket
|
||||
doesn't stop the kernel queueing connections while the accept loop is still blocked in accept(),
|
||||
so for a moment after `stop-server` the port can still be connected to."
|
||||
[bind port]
|
||||
(let [deadline (+ (System/nanoTime) 2000000000)]
|
||||
(while (and (accepting? bind port) (< (System/nanoTime) deadline))
|
||||
(Thread/sleep 5))))
|
||||
|
||||
(defn disable!
|
||||
"Stops the server if it's running; returns the status."
|
||||
"Stops the server if it's running, and returns once its port really refuses connections;
|
||||
returns the status."
|
||||
[]
|
||||
(locking state
|
||||
(when-let [{:keys [server]} @state]
|
||||
(when-let [{:keys [server bind port]} @state]
|
||||
(nrepl/stop-server server)
|
||||
(await-closed bind port)
|
||||
(reset! state nil))
|
||||
(status)))
|
||||
|
||||
Reference in New Issue
Block a user