Estoy tratando de depurar un archivo descriptor de la fuga en una aplicación web que se ejecuta en Jetty 7.0.1 en Linux.

La aplicación había sido feliz en ejecución durante un mes o así, cuando las solicitudes comenzó a fallar debido a demasiados archivos abiertos, y Jetty tuvo que ser reiniciado.

java.io.IOException: Cannot run program [external program]: java.io.IOException: error=24, Too many open files
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:459)
    at java.lang.Runtime.exec(Runtime.java:593)
    at org.apache.commons.exec.launcher.Java13CommandLauncher.exec(Java13CommandLauncher.java:58)
    at org.apache.commons.exec.DefaultExecutor.launch(DefaultExecutor.java:246)

Al principio pensé que el problema era con el código que lanza el programa externo, pero el uso de commons-exec y no veo nada de malo:

CommandLine command = new CommandLine("/path/to/command")
    .addArgument("...");
ByteArrayOutputStream errorBuffer = new ByteArrayOutputStream();
Executor executor = new DefaultExecutor();
executor.setWatchdog(new ExecuteWatchdog(PROCESS_TIMEOUT));
executor.setStreamHandler(new PumpStreamHandler(null, errorBuffer));
try {
    executor.execute(command);
} catch (ExecuteException executeException) {
    if (executeException.getExitValue() == EXIT_CODE_TIMEOUT) {
        throw new MyCommandException("timeout");
    } else {
        throw new MyCommandException(errorBuffer.toString("UTF-8"));
    }
}

Listado de abrir archivos en el servidor, puedo ver a un gran número de FIFOs:

# lsof -u jetty
...
java    524 jetty  218w  FIFO        0,6      0t0 19404236 pipe
java    524 jetty  219r  FIFO        0,6      0t0 19404008 pipe
java    524 jetty  220r  FIFO        0,6      0t0 19404237 pipe
java    524 jetty  222r  FIFO        0,6      0t0 19404238 pipe

cuando Jetty comienza hay sólo 10 FIFOs, después de un par de días hay cientos de ellos.

Sé que es un poco vago en esta etapa, pero ¿tiene alguna sugerencia sobre dónde buscar siguiente, o cómo obtener información más detallada acerca de los descriptores de archivo?

  • Vamos a ver algo de código
  • Añadido el código de lanzar el programa externo.
  • Como fuente adicional de información netstat -anp –tcp|grep <PID> –el color puede ser
  • agregar por último bloque después de try-catch y cerca de todos los flujos. Podría ser posible que los flujos no se cierre correctamente y para ello tienes este error. También tenga en cuenta que linux trata de abrir conexiones de la cuenta en abrir archivos, a fin de comprobar ur código para abrir la conexión.
  • Véase también stackoverflow.com/questions/4289447/java-too-many-open-files
InformationsquelleAutor Mirko N. | 2010-01-11

7 Comentarios

  1. 7

    Su programa externo no se comportan correctamente. Eche un vistazo a por qué no lo hace.

    • Así que estás diciendo que es el programa externo que las fugas de descriptores de archivo? Pero ¿por qué detenerse Jetty aclarar todos los FIFOs entonces?
    • De hecho puede terminar de forma anormal en algunos casos, y no puedo evitar que: depende de la entrada del usuario. Pero que bien puede ser el problema, entonces.
    • Aquí está el Hudson problema: hudson.dev.java.net/issues/show_bug.cgi?id=715
    • Hay demasiados archivos abiertos, que es prevención el programa externo de la ejecución. El problema precede el programa externo y por lo tanto no tiene nada que ver con ella. Es por el límite de procesos en cualquier caso, y se aplica para el proceso actual.
  2. 24

    El problema viene de la aplicación de Java (o en una biblioteca que esté utilizando).

    Primera, usted debe leer la totalidad de las salidas (de Google para StreamGobbler), y de pronto!

    Javadoc dice:

    El proceso primario que utiliza estos flujos de
    para alimentar la entrada y obtener una salida de
    el subproceso. Debido a que algunos nativos
    sólo en plataformas proporcionan buffer limitado
    tamaño de la entrada estándar y la salida de
    los arroyos, la falta de diligencia en la escritura
    flujo de entrada o lectura de la secuencia de salida
    del subproceso puede causar la
    subproceso a bloque, e incluso
    interbloqueo.

    En segundo lugar, waitFor() su proceso de terminar.
    A continuación, cierre la entrada, salida y error arroyos.

    Finalmente destroy() su Proceso.

    Mis fuentes:

    • Esta es la respuesta que en realidad contiene información útil.
    • No es necesario destruir el proceso si waitFor() ha logrado. El proceso ya ha terminado.
  3. 8

    Que se ejecute en Linux tengo la sospecha de que se están acabando de descriptores de archivo. Echa un vistazo ulimit. Aquí está un artículo que describe el problema: http://www.cyberciti.biz/faq/linux-increase-the-maximum-number-of-open-files/

    • Este se puede obtener hasta 2 meses de tiempo de ejecución! (Este es un curita en el mejor.)
    • Has vuelto a confirmar el síntoma, pero no una cura real.
    • De hecho, me hicieron aumentar el límite en /etc/security/limits.conf ya por otras razones.
    • Esto al menos se puede resolver nuestro problema. La aplicación (3ª Parte) es la apertura de más de 1024. NO hay ninguna fuga, pero el límite es demasiado bajo. Establecer el límite a 65535 como se sugiere en este artículo. Parece que el problema se ha ido.
  4. 5

    No conocer la naturaleza de su aplicación, pero he visto este error se manifiesta varias veces debido a un grupo de conexión de fugas, por lo que sería digno de la comprobación hacia fuera. En Linux, las conexiones de socket consumir descriptores de archivo, así como archivos de sistema de archivo. Sólo un pensamiento.

  5. 5

    Aparte de buscar en la raíz de la causa de problemas como archivo de fugas, etc. con el fin de hacer un legítimo aumento de los «archivos abiertos» límite y tiene que persisten a través de los reinicios, considere la posibilidad de editar

    /etc/security/limits.conf

    añadiendo algo como esto

    jetty soft nofile 2048
    jetty hard nofile 4096

    donde «jetty» es el nombre de usuario en este caso. Para más detalles sobre los límites.conf, consulte http://linux.die.net/man/5/limits.conf

    cierre la sesión y, a continuación, inicie la sesión de nuevo y ejecutar

    ulimit -n

    para comprobar que el cambio ha tenido lugar. Nuevos procesos por parte de este usuario debe cumplir ahora con este cambio. En este enlace parece describir cómo aplicar el límite ya que los procesos de ejecución, pero no lo he probado.

    El límite predeterminado de 1024 puede ser demasiado baja para grandes aplicaciones Java.

  6. 2

    Usted puede manejar el fds a ti mismo. El exec en java devuelve un objeto de Proceso. De forma intermitente comprobar si el proceso aún está en marcha. Una vez que se ha completado cerca de los procesos STDERR, STDIN y STDOUT secuencias (por ejemplo, proc.getErrorStream.close()). Para mitigar las pérdidas.

Dejar respuesta

Please enter your comment!
Please enter your name here