La aplicación Flask ya no funciona desde cygwin cuando se configura en modo desarrollador

Este problema ocurrió inmediatamente después de intentar ejecutar mi aplicación Python Flask en segundo plano usando:

$python app.py &

Esto falló de inmediato. Posteriormente, cualquier bash futuro de ejecutar la aplicación, lo que he hecho antes sin ningún problema, termina generando este error:

  $ python app.py Running on http://127.0.0.1:8050/ Debugger PIN: 962-843-370 * Serving Flask app "app" (lazy loading) * Environment: development * Debug mode: on 2 [main] python3.6m 37104 child_info_fork::abort: unable to remap _lbfgsb.cpython-36m-x86_64-cygwin.dll to same address as parent (0x48E0000) - try running rebaseall Traceback (most recent call last): File "app.py", line 644, in  app.run_server(debug=util.DEBUG) File "/cygdrive/c/Users/mkupfer/Desktop/my_documents/01_Visualizations/eurostat/venv/lib/python3.6/site-packages/dash/dash.py", line 1293, in run_server **flask_run_options) File "/cygdrive/c/Users/mkupfer/Desktop/my_documents/01_Visualizations/eurostat/venv/lib/python3.6/site-packages/flask/app.py", line 943, in run run_simple(host, port, self, **options) File "/cygdrive/c/Users/mkupfer/Desktop/my_documents/01_Visualizations/eurostat/venv/lib/python3.6/site-packages/werkzeug/serving.py", line 812, in run_simple reloader_type) File "/cygdrive/c/Users/mkupfer/Desktop/my_documents/01_Visualizations/eurostat/venv/lib/python3.6/site-packages/werkzeug/_reloader.py", line 275, in run_with_reloader sys.exit(reloader.restart_with_reloader()) File "/cygdrive/c/Users/mkupfer/Desktop/my_documents/01_Visualizations/eurostat/venv/lib/python3.6/site-packages/werkzeug/_reloader.py", line 132, in restart_with_reloader close_fds=False) File "/usr/lib/python3.6/subprocess.py", line 267, in call with Popen(*popenargs, **kwargs) as p: File "/usr/lib/python3.6/subprocess.py", line 709, in __init__ restre_signals, start_new_session) File "/usr/lib/python3.6/subprocess.py", line 1275, in _execute_child restre_signals, start_new_session, preexec_fn) BlockingIOError: [Errno 11] Resource temporarily unavailable 

El error parece deberse a la ejecución en modo desarrollador ya que cuando ejecuto con app.run_server(debug=False) (por cierto, util.DEBUG está configurado como True en mi entorno local), la aplicación funciona bien, pero no lo hago. Obtener recarga en caliente que es importante para mí.

He intentado rebasar cygwin según esta publicación https://superuser.com/a/194537/276726 , pero esto no solucionó nada.

También he intentado crear un archivo de rebase especial siguiendo los pasos de esta publicación , pero eso tampoco ayudó.

La aplicación funciona en modo de desarrollo desde mi línea de comandos de Windows, así que esa es mi solución temporal por ahora, pero me encantaría que mi configuración de Cygwin se ejecute correctamente de nuevo.

¡Gracias por la ayuda!

Te encuentras con un problema bastante común en el mundo Cygwin . Hay muchas direcciones URL que mencionan (tratan), pero voy a enumerar las que encontré:

  1. [SO]: Error de Cygwin: “-bash: fork: reintentar: el recurso no está disponible temporalmente”
  2. [SO]: problema de Cygwin – no se puede reasignar; misma dirección que el padre
  3. [Superusuario]: Error fatal de Cygwin que no se puede reasignar. ¿Qué significa?
  4. [WordPress]: Cygwin y Rails: no pueden volver a asignar la misma dirección que el padre; murió esperando la carga de dll, errno 11
  5. [SO]: error de Cygwin: “child_info_fork :: abort: cargado en otra dirección:”

La “magia detrás de escena” está muy bien explicada en [Cygwin]: Problemas con la creación de procesos (los énfasis son míos):

La semántica de fork requiere que un proceso hijo bifurcado tenga exactamente el mismo diseño de espacio de direcciones que su padre. Sin embargo, Windows no proporciona soporte nativo para clonar el espacio de direcciones entre procesos y varias características socavan activamente una implementación de fork confiable. Tres cuestiones son especialmente frecuentes:

  • Colisiones de direcciones base DLL. A diferencia de las bibliotecas compartidas * nix, que utilizan “código independiente de la posición”, las bibliotecas compartidas de Windows asumen una dirección base fija. Cada vez que los rangos de direcciones cableadas de dos DLL chocan (lo que ocurre con bastante frecuencia), el cargador de Windows debe “cambiar” uno de ellos a una dirección diferente. Sin embargo, puede que no resuelva las colisiones de manera consistente, y puede cambiar el tamaño de una dll diferente y / o moverla a una dirección diferente cada vez. Cygwin generalmente puede compensar este efecto cuando involucra bibliotecas abiertas dinámicamente, pero las colisiones entre las dlls vinculadas estáticamente (dependencias conocidas en el momento de la comstackción) se resuelven antes de que cygwin1.dll inicialice y no se puedan cygwin1.dll posteriormente. Este problema solo puede resolverse eliminando los conflictos de direcciones base que causan el problema, generalmente utilizando la herramienta rebaseall .
  • Asignación de espacio de direcciones al azar (ASLR). A partir de Vista, Windows implementa ASLR, lo que significa que las stacks de hilos, el montón, los archivos asignados en memoria y los dlls vinculados estáticamente se colocan en ubicaciones diferentes (aleatorias) en cada proceso. Este comportamiento interfiere con una fork adecuada, y si un objeto inamovible (stack de proceso o dll del sistema) termina en la ubicación incorrecta, Cygwin no puede hacer nada para compensar (aunque lo volverá a intentar automáticamente).

Se intenta un solucionador de problemas en [Cygwin.FAQ]: 4.45. ¿Cómo soluciono fallos de fork ()? ( énfasis todavía mío). Con el riesgo de enviar por correo basura la respuesta, la pegaré aquí:

Desafortunadamente, Windows no utiliza el modelo de creación de procesos fork / exec que se encuentra en sistemas operativos similares a UNIX, por lo que es difícil para Cygwin implementar una fork() fiable y correcta, que puede generar mensajes de error como:

  • no se puede reasignar a la misma dirección que el padre
  • no podría asignar montón
  • murió esperando la carga dll
  • niño -1: murió esperando a que se ejecute longjmp antes de la inicialización
  • STATUS_ACCESS_VIOLATION
  • Recurso temporalmente no disponible

Soluciones potenciales para los errores anteriores:

  • Reinicie cualquier proceso que esté intentando (y falla) usar fork() . A veces, Windows configura un entorno de proceso que es incluso más hostil para fork() de lo habitual.
  • Asegúrese de haber eliminado (no solo deshabilitado) todo el software en el BLODA .
  • Cambie de Cygwin de 32 bits a Cygwin de 64 bits, si su SO y CPU lo admiten. Con el espacio de dirección más grande, la horquilla () es menos probable que falle.
  • Intente configurar la variable de entorno CYGWIN en “detect_bloda”, que habilita un poco de depuración adicional, lo que puede indicar qué otro software está causando el problema.

    Vea este correo para más información.

  • Forzar una rebase completa: ejecute rebase-trigger fullrebase , salga de todos los progtwigs de Cygwin y ejecute la configuración de Cygwin .

    De forma predeterminada, el progtwig de instalación de Cygwin realiza automáticamente una rebase incremental de los archivos recién instalados. Forzar un rebase completo hace que el mapa de rebase se borre antes de hacer el rebase.

    Consulte / usr / share / doc / rebase / README y /usr/share/doc/Cygwin/_autorebase.README para obtener más detalles .

    Tenga en cuenta que la instalación de nuevos paquetes o la actualización de los existentes deshace los efectos de rebase y con frecuencia hace que vuelvan a aparecer los fallos de fork() .

Consulte la sección de creación de procesos de la Guía del usuario para conocer las razones técnicas por las que es tan difícil hacer que fork() funcione de manera confiable.

Para reproducir el problema, utilicé:

  • Cygwin 32 :
    • La posibilidad de toparse con el problema es mucho mayor.
    • No es mi principal envio de Cygwin.
  • Python 3.6.4 + VEnv
    • Ubicado en /home/cfati/Work/Dev/VEnvs/py_032_03.06.04_test0

Intenté reproducir tu comportamiento exacto (con _lbfgsb * .dll ), pero pip -v install scipy no pudo comstackrlo.
Desde [SciPy]: la instalación de SciPy en Windows describe un proceso bastante complejo, y no tengo ninguna garantía de que al final pueda reproducir el problema, lo intenté con el .dll de numpy (el número se instaló correctamente como una dependencia de scipy ), pero no pude (como efecto secundario, import numpy carga un montón de .dll s), pero llamar a la bifurcación (a través de subprocess.Popen ) no falló.
Luego decidí tomar la materia en mis propias manos y crear un pequeño progtwig que carga algunos archivos .dll , luego se forja (de nuevo, a través de subprocess.Popen ), para hacer que el problema sea lo más reproducible posible.

dll.c :

 #include  #if defined(_WIN32) # define DLL_EXPORT __declspec(dllexport) #else # define DLL_EXPORT #endif DLL_EXPORT int test() { printf("[%s] (%d) - [%s]\n", __FILE__, __LINE__, __FUNCTION__); } 

code.py :

 #!/usr/bin/env python3 import sys import os import subprocess import time import select import random import ctypes DLLS = [os.path.join(os.path.dirname(__file__), "dll{:d}.dll".format(item)) for item in range(2)] def main(): random.seed(os.getpid()) random.shuffle(DLLS) if len(sys.argv) == 1: print("Python {:s} on {:s}\n".format(sys.version.replace("\n", ""), sys.platform)) print("Process 0x{:08X}".format(os.getpid())) for dll in DLLS: ctypes.cdll.LoadLibrary(dll) idx = 0 while sys.stdin not in select.select([sys.stdin], [], [], 1)[0]: p = subprocess.Popen([sys.executable] + sys.argv + [str(idx)]) #p.communicate() time.sleep(1) idx += 1 else: sleep_time = 3 print("Process 0x{:08X} (inner) will end in {:d} seconds".format(os.getpid(), sleep_time)) time.sleep(sleep_time) if __name__ == "__main__": main() 

Notas :

  • El escenario es un poco diferente, en lugar de un módulo de extensión de Python , tengo un .dll regular (ficticio), que bash cargarlo a través de [Python 3]: ctypes – Una biblioteca de funciones foránea para Python . Esto no debería hacer ninguna diferencia, ya que no importa cómo lo vea Python (como un módulo o como un .dll externo) todavía tendrá que cargarlo en el proceso (de la misma manera)
  • El escenario es:
    • Cargo 2 de estos .dll s (en realidad es el mismo .dll copiado con un nombre diferente, por lo que ambos tienen la misma Dirección Base Preferida ), por lo que el 1 st .dll probablemente se cargará en esa dirección, mientras que el siguiente .dll será cargado en una diferente
    • Luego bifurco el proceso, y en el niño, basado en un factor aleatorio, cambio el orden de carga de .dll
    • Cuando el 2 nd .dll se cargará en la base preferida, habrá una inconsistencia con el proceso principal, produciendo el error
  • Al principio, todo estaba en mi cwd , luego (para estar más cerca de tu problema), creé un paquete de Python con los archivos. Tenga en cuenta que no lo hice correctamente (instalación a través de un archivo setup.py ), sino que copié todo manualmente
 [cfati@cfati-5510-0:/cygdrive/e/Work/Dev/StackOverflow/q054370263]> ~/sopr.sh *** Set shorter prompt to better fit when pasted in StackOverflow (or other) pages *** [prompt]> [prompt]> uname -a CYGWIN_NT-10.0-WOW cfati-5510-0 2.11.2(0.329/5/3) 2018-11-08 14:30 i686 Cygwin [prompt]> ls code.py dll.c scipy.txt [prompt]> # List the currently installed packages in the !!! VEENV !!! Python [prompt]> ls -l ~/Work/Dev/VEnvs/py_032_03.06.04_test0/lib/python3.6/site-packages total 33 drwxr-xr-x+ 1 cfati None 0 Jan 30 01:40 __pycache__ -rw-r--r-- 1 cfati None 126 Jan 30 01:40 easy_install.py drwxr-xr-x+ 1 cfati None 0 Feb 2 21:41 numpy drwxr-xr-x+ 1 cfati None 0 Feb 2 21:41 numpy-1.16.1.dist-info drwxr-xr-x+ 1 cfati None 0 Jan 30 01:40 pip drwxr-xr-x+ 1 cfati None 0 Jan 30 01:40 pip-19.0.1.dist-info drwxr-xr-x+ 1 cfati None 0 Jan 30 01:40 pkg_resources drwxr-xr-x+ 1 cfati None 0 Jan 30 01:40 setuptools drwxr-xr-x+ 1 cfati None 0 Jan 30 01:40 setuptools-40.7.1.dist-info drwxr-xr-x+ 1 cfati None 0 Jan 30 01:40 wheel drwxr-xr-x+ 1 cfati None 0 Jan 30 01:40 wheel-0.32.3.dist-info [prompt]> [prompt]> ~/Work/Dev/VEnvs/py_032_03.06.04_test0/bin/python -m q054370263 /home/cfati/Work/Dev/VEnvs/py_032_03.06.04_test0/bin/python: No module named q054370263 [prompt]> # Create the package in site-packages dir [prompt]> mkdir ~/Work/Dev/VEnvs/py_032_03.06.04_test0/lib/python3.6/site-packages/q054370263 [prompt]> cp code.py ~/Work/Dev/VEnvs/py_032_03.06.04_test0/lib/python3.6/site-packages/q054370263/__main__.py [prompt]> gcc -fPIC -shared -o ~/Work/Dev/VEnvs/py_032_03.06.04_test0/lib/python3.6/site-packages/q054370263/dll0.dll dll.c [prompt]> cp ~/Work/Dev/VEnvs/py_032_03.06.04_test0/lib/python3.6/site-packages/q054370263/dll0.dll ~/Work/Dev/VEnvs/py_032_03.06.04_test0/lib/python3.6/site-packages/q054370263/dll1.dll [prompt]> ls code.py dll.c scipy.txt [prompt]> ls -l ~/Work/Dev/VEnvs/py_032_03.06.04_test0/lib/python3.6/site-packages/q054370263 total 260 -rwxr-x--- 1 cfati None 1012 Feb 3 12:39 __main__.py -rwxr-xr-x 1 cfati None 129844 Feb 3 12:22 dll0.dll -rwxr-xr-x 1 cfati None 129844 Feb 3 12:22 dll1.dll [prompt]> [prompt]> # Attempt to reproduce the problem by simply running the package [prompt]> ~/Work/Dev/VEnvs/py_032_03.06.04_test0/bin/python -m q054370263 Python 3.6.4 (default, Jan 7 2018, 17:45:56) [GCC 6.4.0] on cygwin Process 0x00001B38 18 [main] python3 21616 child_info_fork::abort: address space needed by 'dll0.dll' (0xD90000) is already occupied Traceback (most recent call last): File "/usr/lib/python3.6/runpy.py", line 193, in _run_module_as_main "__main__", mod_spec) File "/usr/lib/python3.6/runpy.py", line 85, in _run_code exec(code, run_globals) File "/home/cfati/Work/Dev/VEnvs/py_032_03.06.04_test0/lib/python3.6/site-packages/q054370263/__main__.py", line 37, in  main() File "/home/cfati/Work/Dev/VEnvs/py_032_03.06.04_test0/lib/python3.6/site-packages/q054370263/__main__.py", line 25, in main p = subprocess.Popen([sys.executable] + sys.argv + [str(idx)]) File "/usr/lib/python3.6/subprocess.py", line 709, in __init__ restre_signals, start_new_session) File "/usr/lib/python3.6/subprocess.py", line 1275, in _execute_child restre_signals, start_new_session, preexec_fn) BlockingIOError: [Errno 11] Resource temporarily unavailable [prompt]> [prompt]> ~/Work/Dev/VEnvs/py_032_03.06.04_test0/bin/python -m q054370263 Python 3.6.4 (default, Jan 7 2018, 17:45:56) [GCC 6.4.0] on cygwin Process 0x000055E8 Process 0x00005764 (inner) will end in 3 seconds 1 [main] python3 21224 child_info_fork::abort: address space needed by 'dll1.dll' (0x6D0000) is already occupied Traceback (most recent call last): File "/usr/lib/python3.6/runpy.py", line 193, in _run_module_as_main "__main__", mod_spec) File "/usr/lib/python3.6/runpy.py", line 85, in _run_code exec(code, run_globals) File "/home/cfati/Work/Dev/VEnvs/py_032_03.06.04_test0/lib/python3.6/site-packages/q054370263/__main__.py", line 37, in  main() File "/home/cfati/Work/Dev/VEnvs/py_032_03.06.04_test0/lib/python3.6/site-packages/q054370263/__main__.py", line 25, in main p = subprocess.Popen([sys.executable] + sys.argv + [str(idx)]) File "/usr/lib/python3.6/subprocess.py", line 709, in __init__ restre_signals, start_new_session) File "/usr/lib/python3.6/subprocess.py", line 1275, in _execute_child restre_signals, start_new_session, preexec_fn) BlockingIOError: [Errno 11] Resource temporarily unavailable 

Por lo tanto, el error es bastante reproducible. También me gustaría agregar aquí los detalles de .dll ( Dependency Walker ):

Img0

¿Por qué una rebase regular ( rebaseall ) resuelve el problema?

  • Los paquetes de Cygwin tienen una secuencia de comandos posterior a la instalación que llama a rebase en sus .dll s
  • búsquedas de rebase en las rutas de la biblioteca estándar ( / lib , / usr / lib , …). Eso se puede ajustar, de acuerdo con /usr/share/doc/Cygwin/_autorebase.README :

    Los paquetes pueden dar a conocer las ubicaciones potenciales de dichos objetos dynamics al soltar un archivo (llamado así por el paquete) en /var/lib/rebase/dynpath.d/ . Si los usuarios instalan objetos dynamics, estas ubicaciones deben publicarse en /var/lib/rebase/user.d/ (el nombre del archivo debe ser idéntico al nombre de usuario si hay varios usuarios en este sistema)

    Python requiere tal ajuste, debido a los paquetes que pueden contener .dll s

  • los paquetes similares a pip no tienen una secuencia de comandos posterior a la instalación (que volvería a borrar su .dll s)
  • El VEnv está en la ruta de acceso principal del usuario que no está en las rutas de la biblioteca estándar (por lo tanto, incluso un rebaseall los ignorará)

Tenga en cuenta que todas las .dll rebasadas se almacenan en una base de datos : /etc/rebase.db(.${ARCH}) .

 [prompt]> ls /var/lib/rebase/dynpath.d/ perl python2 python3 [prompt]> cat /var/lib/rebase/dynpath.d/python3 /usr/lib/python3.6/site-packages [prompt]> ls /var/lib/rebase/user.d/ [prompt]> [prompt]> grep -r "dll0.dll" /etc/rebase.db.i386 [prompt]> 

Para que los archivos .dll sean seleccionados por las herramientas de rebase , deben publicarse. Eso se puede hacer de 2 maneras:

  • Especifíquelos en una de las ubicaciones personalizadas, de modo que en la siguiente rebase completa ya no serán ignorados (simplemente agregue el directorio VEnv y otros, si los hay):

     [prompt]> echo /home/cfati/Work/Dev/VEnvs/py_032_03.06.04_test0 >/var/lib/rebase/user.d/${USER} [prompt]> cat /var/lib/rebase/user.d/cfati /home/cfati/Work/Dev/VEnvs/py_032_03.06.04_test0 
  • Reajustar manualmente el .dll s

Ambos trabajaron para mí, pero voy a ejemplificar solo en la variante (ya que es más simple). El proceso consta de 2 pasos:

  • Crea una lista de todos los .dll que necesitan ser rebasados

     [prompt]> find /home/cfati/Work/Dev/VEnvs/py_032_03.06.04_test0 -name "*.dll" -o -name "*.so">/tmp/to_rebase.txt [prompt]> ls -l /tmp/to_rebase.txt -rw-r--r-- 1 cfati None 1773 Feb 3 13:05 /tmp/to_rebase.txt [prompt]> cat /tmp/to_rebase.txt /home/cfati/Work/Dev/VEnvs/py_032_03.06.04_test0/lib/python3.6/site-packages/numpy/core/_dummy.cpython-36m-i386-cygwin.dll /home/cfati/Work/Dev/VEnvs/py_032_03.06.04_test0/lib/python3.6/site-packages/numpy/core/_multiarray_module_test.cpython-36m-i386-cygwin.dll /home/cfati/Work/Dev/VEnvs/py_032_03.06.04_test0/lib/python3.6/site-packages/numpy/core/_multiarray_tests.cpython-36m-i386-cygwin.dll /home/cfati/Work/Dev/VEnvs/py_032_03.06.04_test0/lib/python3.6/site-packages/numpy/core/_multiarray_umath.cpython-36m-i386-cygwin.dll /home/cfati/Work/Dev/VEnvs/py_032_03.06.04_test0/lib/python3.6/site-packages/numpy/core/_operand_flag_tests.cpython-36m-i386-cygwin.dll /home/cfati/Work/Dev/VEnvs/py_032_03.06.04_test0/lib/python3.6/site-packages/numpy/core/_rational_tests.cpython-36m-i386-cygwin.dll /home/cfati/Work/Dev/VEnvs/py_032_03.06.04_test0/lib/python3.6/site-packages/numpy/core/_struct_ufunc_tests.cpython-36m-i386-cygwin.dll /home/cfati/Work/Dev/VEnvs/py_032_03.06.04_test0/lib/python3.6/site-packages/numpy/core/_umath_tests.cpython-36m-i386-cygwin.dll /home/cfati/Work/Dev/VEnvs/py_032_03.06.04_test0/lib/python3.6/site-packages/numpy/fft/fftpack_lite.cpython-36m-i386-cygwin.dll /home/cfati/Work/Dev/VEnvs/py_032_03.06.04_test0/lib/python3.6/site-packages/numpy/linalg/lapack_lite.cpython-36m-i386-cygwin.dll /home/cfati/Work/Dev/VEnvs/py_032_03.06.04_test0/lib/python3.6/site-packages/numpy/linalg/_umath_linalg.cpython-36m-i386-cygwin.dll /home/cfati/Work/Dev/VEnvs/py_032_03.06.04_test0/lib/python3.6/site-packages/numpy/random/mtrand.cpython-36m-i386-cygwin.dll /home/cfati/Work/Dev/VEnvs/py_032_03.06.04_test0/lib/python3.6/site-packages/q054370263/dll0.dll /home/cfati/Work/Dev/VEnvs/py_032_03.06.04_test0/lib/python3.6/site-packages/q054370263/dll1.dll 
  • Realizar la rebase

    • Todos los procesos de Cygwin deben estar cerrados (incluidos los servicios: por ejemplo, sshd )
    • Inicié el comando desde dash.exe (se inició directamente desde Win , desde Cygwin bin dir) y no desde Mintty (observe el aviso)
     $ /bin/rebaseall -v -T /tmp/to_rebase.txt ... /usr/bin/cygargp-0.dll: new base = 6e7c0000, new size = 20000 /home/cfati/Work/Dev/VEnvs/py_032_03.06.04_test0/lib/python3.6/site-packages/q054370263/dll1.dll: new base = 6e7e0000, new size = 30000 /home/cfati/Work/Dev/VEnvs/py_032_03.06.04_test0/lib/python3.6/site-packages/q054370263/dll0.dll: new base = 6e810000, new size = 30000 /home/cfati/Work/Dev/VEnvs/py_032_03.06.04_test0/lib/python3.6/site-packages/numpy/random/mtrand.cpython-36m-i386-cygwin.dll: new base = 6e840000, new size = 280000 ... 

La ventana actualizada de Dependency Walker (verifique su Base Preferida y compárela con la de la imagen anterior):

Img1

Y también la “consulta” de DB de rebase (ahora de Mintty ):

 [prompt]> grep -r "dll0.dll" /etc/rebase.db.i386 Binary file /etc/rebase.db.i386 matches 

Lo que es más importante, ejecutando el código :

 [prompt]> ~/Work/Dev/VEnvs/py_032_03.06.04_test0/bin/python -m q054370263 Python 3.6.4 (default, Jan 7 2018, 17:45:56) [GCC 6.4.0] on cygwin Process 0x000052D0 Process 0x00004634 (inner) will end in 3 seconds Process 0x00004864 (inner) will end in 3 seconds Process 0x00005CFC (inner) will end in 3 seconds Process 0x00005A5C (inner) will end in 3 seconds Process 0x00005098 (inner) will end in 3 seconds Process 0x00005840 (inner) will end in 3 seconds Process 0x000058C4 (inner) will end in 3 seconds Process 0x000051DC (inner) will end in 3 seconds Process 0x00001A5C (inner) will end in 3 seconds Process 0x00003D2C (inner) will end in 3 seconds Process 0x00000DA0 (inner) will end in 3 seconds 

Como se ve, es capaz de bifurcarse varias veces (solo se detuvo porque presioné Intro ).