+25
-3
@@ -1,7 +1,8 @@
|
|||||||
(ns tbd.nrepl.core
|
(ns tbd.nrepl.core
|
||||||
"The on-demand nREPL debug server. No HTTP here."
|
"The on-demand nREPL debug server. No HTTP here."
|
||||||
(:require [clojure.string :as str]
|
(:require [clojure.string :as str]
|
||||||
[nrepl.server :as nrepl]))
|
[nrepl.server :as nrepl])
|
||||||
|
(:import (java.net InetAddress InetSocketAddress Socket)))
|
||||||
|
|
||||||
(def default-port 7888)
|
(def default-port 7888)
|
||||||
|
|
||||||
@@ -35,11 +36,32 @@
|
|||||||
(reset! state {:server server :bind bind :port (:port server)})))
|
(reset! state {:server server :bind bind :port (:port server)})))
|
||||||
(status)))
|
(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!
|
(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
|
(locking state
|
||||||
(when-let [{:keys [server]} @state]
|
(when-let [{:keys [server bind port]} @state]
|
||||||
(nrepl/stop-server server)
|
(nrepl/stop-server server)
|
||||||
|
(await-closed bind port)
|
||||||
(reset! state nil))
|
(reset! state nil))
|
||||||
(status)))
|
(status)))
|
||||||
|
|||||||
Reference in New Issue
Block a user