Завершение пула потоков сервера Jetty, если исключение при start ()

Я пишу встроенное приложение Jetty в Clojure и использую следующее в качестве основного пространства имен:

(ns rudkus.core
  (:require [clojure.tools.cli :as cli]
            [ring.adapter.jetty :as jetty])
  (:gen-class))

(defn handler [request]
  {:status 200
   :headers {"Content-Type" "text/html"}
   :body "Hello, World!"})

(def ^{:private true} server (atom nil))

(defn start [port]
  (swap! server #(if (not (nil? %))
                  (throw (IllegalStateException. "Server already started."))
                  (jetty/run-jetty handler
                                   {:port port
                                    :join? false}))))

(defn stop []
  (swap! server #(if (nil? %)
                  (throw (IllegalStateException. "Server already stopped."))
                  (do (.stop %)
                      nil))))

(defn -main [& args]
  (let [[options extra-args banner] (cli/cli args
                                             ["-p" "--port" "Port" :default 80 :parse-fn #(Integer. %)])]
    (if (not-empty extra-args)
      (println banner)
      (start (:port options)))))

Это работает нормально - я хочу иметь возможность запускать и останавливать через REPL, а также запускать и запускать с консоли, на которой работает JAR (хотя, если есть лучший шаблон для запуска / остановки программы Clojure-Ring-Jetty , Хотелось бы знать). Проблема в том, если я бегу

lein run

or

lein trampoline run

и есть исключение, выброшенное jetty / run-jetty (которое обертывает вызов Server.start ()) - например, на моем MacBook Pro, если я пытаюсь запустить сервер Jetty на порту 80, он выключается - программа Clojure не не выйду. Однако исключение составляет поток «основной». Так почему бы не выйти из программы? Единственное, о чем я могу думать, это о том, что у Jetty плавают потоки. Но start () не удалось !!! Итак, что делают / делают эти потоки (пулы)?

Это Java, Clojure, Leiningen, Jetty или Ring?

РЕДАКТИРОВАТЬ:

Вот трассировка стека:

$ java -jar rudkus-0.1.0-SNAPSHOT-standalone.jar
2012-09-09 15:54:59.664:INFO:oejs.Server:jetty-7.x.y-SNAPSHOT
2012-09-09 15:54:59.803:WARN:oejuc.AbstractLifeCycle:FAILED [email protected]:80: java.net.SocketException: Permission denied
java.net.SocketException: Permission denied
    at sun.nio.ch.Net.bind(Native Method)
    at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:124)
    at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:59)
    at org.eclipse.jetty.server.nio.SelectChannelConnector.open(SelectChannelConnector.java:173)
    at org.eclipse.jetty.server.AbstractConnector.doStart(AbstractConnector.java:311)
    at org.eclipse.jetty.server.nio.SelectChannelConnector.doStart(SelectChannelConnector.java:251)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59)
    at org.eclipse.jetty.server.Server.doStart(Server.java:272)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59)
    at ring.adapter.jetty$run_jetty.invoke(jetty.clj:86)
    at rudkus.core$start$fn__16.invoke(core.clj:16)
    at clojure.lang.Atom.swap(Atom.java:37)
    at clojure.core$swap_BANG_.invoke(core.clj:2108)
    at rudkus.core$start.invoke(core.clj:14)
    at rudkus.core$_main.doInvoke(core.clj:31)
    at clojure.lang.RestFn.invoke(RestFn.java:397)
    at clojure.lang.AFn.applyToHelper(AFn.java:159)
    at clojure.lang.RestFn.applyTo(RestFn.java:132)
    at rudkus.core.main(Unknown Source)
2012-09-09 15:54:59.806:WARN:oejuc.AbstractLifeCycle:FAILED org.eclipse.jetty.server.Server@6e5dfaf1: java.net.SocketException: Permission denied
java.net.SocketException: Permission denied
    at sun.nio.ch.Net.bind(Native Method)
    at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:124)
    at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:59)
    at org.eclipse.jetty.server.nio.SelectChannelConnector.open(SelectChannelConnector.java:173)
    at org.eclipse.jetty.server.AbstractConnector.doStart(AbstractConnector.java:311)
    at org.eclipse.jetty.server.nio.SelectChannelConnector.doStart(SelectChannelConnector.java:251)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59)
    at org.eclipse.jetty.server.Server.doStart(Server.java:272)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59)
    at ring.adapter.jetty$run_jetty.invoke(jetty.clj:86)
    at rudkus.core$start$fn__16.invoke(core.clj:16)
    at clojure.lang.Atom.swap(Atom.java:37)
    at clojure.core$swap_BANG_.invoke(core.clj:2108)
    at rudkus.core$start.invoke(core.clj:14)
    at rudkus.core$_main.doInvoke(core.clj:31)
    at clojure.lang.RestFn.invoke(RestFn.java:397)
    at clojure.lang.AFn.applyToHelper(AFn.java:159)
    at clojure.lang.RestFn.applyTo(RestFn.java:132)
    at rudkus.core.main(Unknown Source)
Exception in thread "main" java.net.SocketException: Permission denied
    at sun.nio.ch.Net.bind(Native Method)
    at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:124)
    at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:59)
    at org.eclipse.jetty.server.nio.SelectChannelConnector.open(SelectChannelConnector.java:173)
    at org.eclipse.jetty.server.AbstractConnector.doStart(AbstractConnector.java:311)
    at org.eclipse.jetty.server.nio.SelectChannelConnector.doStart(SelectChannelConnector.java:251)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59)
    at org.eclipse.jetty.server.Server.doStart(Server.java:272)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:59)
    at ring.adapter.jetty$run_jetty.invoke(jetty.clj:86)
    at rudkus.core$start$fn__16.invoke(core.clj:16)
    at clojure.lang.Atom.swap(Atom.java:37)
    at clojure.core$swap_BANG_.invoke(core.clj:2108)
    at rudkus.core$start.invoke(core.clj:14)
    at rudkus.core$_main.doInvoke(core.clj:31)
    at clojure.lang.RestFn.invoke(RestFn.java:397)
    at clojure.lang.AFn.applyToHelper(AFn.java:159)
    at clojure.lang.RestFn.applyTo(RestFn.java:132)
    at rudkus.core.main(Unknown Source)

person jennykwan    schedule 08.09.2012    source источник
comment
Возможно, -main порождает потоки, не являющиеся демонами (см. stackoverflow.com/questions/2213340/), но невозможно узнать наверняка без трассировки стека.   -  person noahlz    schedule 09.09.2012


Ответы (1)


есть решение, если вы посмотрите на этот код (найденный как ответ на первой странице результатов Google): исходный код, содержащий метод contextStartupFailed () Однако это решение не сработало для меня, поскольку он запрашивает поле с именем _unavailable с использованием отражения, а моя версия Jetty (8.1.8.v20121106) не имеет такого поля.

Однако теперь Jetty поддерживает кое-что получше. Для меня работает следующее:

  protected static void contextStartupFailed(WebAppContext pContext) throws Exception {

  Throwable failedException = pContext.getUnavailableException();

  if (failedException != null) {
     throw new RuntimeException("Error starting WebContext of Jetty.", failedException);
  }

}

Я вызываю этот метод сразу после запуска Jetty. Конечно, это работает, только если у вас есть WebAppContext.

person Claus Gebert    schedule 26.11.2012