Permalink
Browse files

Fix "too many open files" errors.

This patch uses `io/reader` in conjunction with `with-open` to prevent
"too many open files" errors. This happens in a browser REPL when
evaluating a file that references a couple of other files multiple
times.
  • Loading branch information...
1 parent 7c49efc commit 905c64445faa1c60e21b66fb226982759b0d4001 @r0man r0man committed with swannodette Jan 28, 2014
Showing with 43 additions and 33 deletions.
  1. +5 −4 src/clj/cljs/analyzer.clj
  2. +24 −19 src/clj/cljs/closure.clj
  3. +6 −5 src/clj/cljs/compiler.clj
  4. +8 −5 src/clj/cljs/repl/rhino.clj
@@ -1533,8 +1533,9 @@
argument, which the reader will use in any emitted errors."
([f] (forms-seq f (source-path f)))
([f filename]
- (let [rdr (readers/indexing-push-back-reader
- (java.io.PushbackReader. (io/reader f)) 1 filename)
+ (let [rdr (io/reader f)
+ pbr (readers/indexing-push-back-reader
+ (java.io.PushbackReader. rdr) 1 filename)
data-readers tags/*cljs-data-readers*
forms-seq*
(fn forms-seq* []
@@ -1546,9 +1547,9 @@ argument, which the reader will use in any emitted errors."
(apply merge
((juxt :requires :require-macros)
(get-namespace *cljs-ns*)))]
- (reader/read rdr nil eof-sentinel))]
+ (reader/read pbr nil eof-sentinel))]
(if (identical? form eof-sentinel)
- nil
+ (.close rdr)
(cons form (forms-seq*))))))]
(forms-seq*))))
View
@@ -305,16 +305,18 @@
(-provides [this] (map name (:provides this)))
(-requires [this] (map name (:requires this)))
(-source [this] (if-let [s (:source this)]
- s
- (slurp (io/reader (-url this))))))
+ s (with-open [reader (io/reader (-url this))]
+ (slurp reader)))))
(defrecord JavaScriptFile [foreign ^URL url ^URL source-url provides requires lines source-map]
IJavaScript
(-foreign? [this] foreign)
(-url [this] url)
(-provides [this] provides)
(-requires [this] requires)
- (-source [this] (slurp (io/reader url)))
+ (-source [this]
+ (with-open [reader (io/reader url)]
+ (slurp reader)))
ISourceMap
(-source-url [this] source-url)
(-source-map [this] source-map))
@@ -453,8 +455,9 @@
(defn jar-file-to-disk
"Copy a file contained within a jar to disk. Return the created file."
[url out-dir]
- (let [out-file (io/file out-dir (path-from-jarfile url))
- content (slurp (io/reader url))]
+ (let [out-file (io/file out-dir (path-from-jarfile url))
+ content (with-open [reader (io/reader url)]
+ (slurp reader))]
(do (comp/mkdirs out-file)
(spit out-file content)
out-file)))
@@ -555,10 +558,9 @@
([path cp-only?]
(let [find-func (if cp-only? find-js-classpath find-js-resources)
graph-node (fn [u]
- (-> (io/reader u)
- line-seq
- parse-js-ns
- (assoc :url u)))]
+ (with-open [reader (io/reader u)]
+ (-> reader line-seq parse-js-ns
+ (assoc :url u))))]
(let [js-sources (find-js-resources path)]
(filter #(seq (:provides %)) (map graph-node js-sources))))))
@@ -590,15 +592,17 @@
(letfn [(parse-list [s] (when (> (count s) 0)
(-> (.substring ^String s 1 (dec (count s)))
(string/split #"'\s*,\s*'"))))]
- (->> (line-seq (io/reader (io/resource "goog/deps.js")))
- (map #(re-matches #"^goog\.addDependency\(['\"](.*)['\"],\s*\[(.*)\],\s*\[(.*)\]\);.*" %))
- (remove nil?)
- (map #(drop 1 %))
- (remove #(.startsWith ^String (first %) "../../third_party"))
- (map #(hash-map :file (str "goog/"(first %))
- :provides (parse-list (second %))
- :requires (parse-list (last %))
- :group :goog)))))
+ (with-open [reader (io/reader (io/resource "goog/deps.js"))]
+ (->> (line-seq reader)
+ (map #(re-matches #"^goog\.addDependency\(['\"](.*)['\"],\s*\[(.*)\],\s*\[(.*)\]\);.*" %))
+ (remove nil?)
+ (map #(drop 1 %))
+ (remove #(.startsWith ^String (first %) "../../third_party"))
+ (map #(hash-map :file (str "goog/"(first %))
+ :provides (parse-list (second %))
+ :requires (parse-list (last %))
+ :group :goog))
+ (doall)))))
(def goog-dependencies (memoize goog-dependencies*))
@@ -969,7 +973,8 @@
;; write something from a jar file to disk
(source-on-disk {}
{:url (io/resource "goog/base.js")
- :source (slurp (io/reader (io/resource "goog/base.js")))})
+ :source (with-open [reader (io/reader (io/resource "goog/base.js"))]
+ (slurp reader))})
;; doesn't write a file that is already on disk
(source-on-disk {} {:url (io/resource "cljs/core.cljs")})
)
View
@@ -913,10 +913,10 @@
ret)))))))))
(defn compiled-by-version [^File f]
- (let [match (->> (io/reader f)
- line-seq first
- (re-matches #".*ClojureScript (.*)$"))]
- (and match (second match))))
+ (with-open [reader (io/reader f)]
+ (let [match (->> reader line-seq first
+ (re-matches #".*ClojureScript (.*)$"))]
+ (and match (second match)))))
(defn requires-compilation?
"Return true if the src file requires compilation."
@@ -960,7 +960,8 @@
:file dest
:source-file src}
(when (and dest (.exists ^File dest))
- {:lines (-> (io/reader dest) line-seq count)})))
+ {:lines (with-open [reader (io/reader dest)]
+ (-> reader line-seq count))})))
(recur (rest forms)))))))]
;; TODO this _was_ a reset! of the old ana/namespaces atom; should we capture and
;; then restore the entirety of env/*compiler* here instead?
@@ -78,15 +78,17 @@
(binding [ana/*cljs-ns* 'cljs.user]
(repl/load-stream repl-env cljs-path res))
(if-let [res (io/resource js-path)]
- (-eval (io/reader res) repl-env js-path 1)
+ (with-open [reader (io/reader res)]
+ (-eval reader repl-env js-path 1))
(throw (Exception. (str "Cannot find " cljs-path " or " js-path " in classpath")))))
(swap! (:loaded-libs repl-env) conj rule))))
(defn load-javascript [repl-env ns url]
(let [missing (remove #(contains? @(:loaded-libs repl-env) %) ns)]
(when (seq missing)
- (do (try
- (-eval (io/reader url) repl-env (.toString url) 1)
+ (do (try
+ (with-open [reader (io/reader url)]
+ (-eval reader repl-env (.toString url) 1))
;; TODO: don't show errors for goog/base.js line number 105
(catch Throwable ex (println (.getMessage ex))))
(swap! (:loaded-libs repl-env) (partial apply conj) missing)))))
@@ -137,8 +139,9 @@
(-eval r new-repl-env "goog/base.js" 1))
(-eval bootjs new-repl-env "bootjs" 1)
;; Load deps.js line-by-line to avoid 64K method limit
- (doseq [^String line (line-seq (io/reader deps))]
- (-eval line new-repl-env "goog/deps.js" 1))
+ (with-open [reader (io/reader deps)]
+ (doseq [^String line (line-seq reader)]
+ (-eval line new-repl-env "goog/deps.js" 1)))
new-repl-env))
(comment

0 comments on commit 905c644

Please sign in to comment.