             (map string/trim (string/split-lines s)))))
 
 
+(defn die-on-exit-or-error
+  [a-future error]
+  (when error
+    (trace/print-stack-trace error))
+  (die "thread died unexpectedly"))
+
+
 (defn -main [& args]
   ;; work around dangerous default behaviour in Clojure
   ;; (alter-var-root #'*read-eval* (constantly false))

    (catch Throwable err
      err)))

(let [call-counter (atom 0)]
  (defn reap-futures
    []
    (swap! call-counter inc)
    (when (zero? (rem @call-counter 240))
      (logging/info "reaping futures" @call-counter))
    (try
      (doseq [[a-future val] @future-map]
        (when (realized? a-future)
          (if-let [error (deref-exception a-future)]
            (do
              (logging/error "************* error in future" (str a-future) error val)
              ((:cleanup-on-error val))))
          (swap! future-map dissoc a-future)))
      (catch Throwable err
        (logging/error "error occured in reap-futures" err)))))


(defn map-from-routing-key-string

    (when (zero? (count filesystems))
      (die (str "no filesystems defined in section " inisection " in " iniconfig)))

    (periodically 250 reap-futures)

    (let [futures (doall (for [filesystem filesystems]
                           (future (handle-command-for-filesystem filesystem))))
          wait-for-ever (promise)]
      (periodically 1000 #(watch-futures (constantly futures)
                                         die-on-exit-or-error die-on-exit-or-error))
      @wait-for-ever)))
