Codebase list kitchensink-clojure / fe542d9
(maint) Define our own entropy in `open-port-num`. The current implementation of `open-port-num` relies on the JDK implementation to select a currently-open port. Anecdotally, some implementations have low amounts of entropy for this operation. Change the implementation to uniformly select a random port number in the traditional ephemeral port range of 49152 through 65535, so we're sure we're using the maximum available range regardless of JDK implementation. The anecdotal evidence for the entropy comes from the frequency of port collisions seen in the classifier's integration tests. Up through 2016.4.x, we used a custom random port selection function with entropy equivalent to this one (but which did *not* check to see if the selected port was open), and we saw closed ports in the ~12 ports bound less than once every fifteen runs. Starting in 2017.2.x, we switched to using kitchensink's open-port-num, and we've observed the frequency of collisions to go up dramatically: now we see them, on average, once every other run. This anecdotal evidence is backed up by observing that this new implementation of `open-port-num` returns over twice as many distinct port numbers as the previous one when invoked 60k times during the tests: ~15.9k vs. ~7k. However, this is only testing my JDK implementation; that spread may vary depending on the particular JDK used. Dan Lidral-Porter 6 years ago
1 changed file(s) with 17 addition(s) and 3 deletion(s). Raw diff Collapse all Expand all
10661066 ~@(interleave (repeat g) (map pstep forms))]
10671067 ~g)))
10681068
1069 (defn- port-open?
1070 [port]
1071 (try
1072 (with-open [_ (java.net.ServerSocket. port)]
1073 port)
1074 (catch java.net.BindException e
1075 (when-not (re-find #"already in use" (.getMessage e))
1076 (throw e)))))
1077
10691078 (defn open-port-num
1070 "Returns a currently open port number"
1079 "Returns a currently open port number in the traditional ephemeral port range
1080 of 49152 through 65535."
10711081 []
1072 (with-open [s (java.net.ServerSocket. 0)]
1073 (.getLocalPort s)))
1082 (let [lo 49152
1083 hi 65536] ; one higher because the upper limit is exclusive
1084 (if-let [open-port (some port-open? (shuffle (range lo hi)))]
1085 open-port
1086 (throw (java.net.BindException.
1087 "All ephemeral ports are already in use (Bind failed)")))))
10741088
10751089 (defmacro assoc-if-new
10761090 "Assocs the provided values with the corresponding keys if and only