Приложение Flask больше не работает из cygwin при переходе в режим разработчика - PullRequest
0 голосов
/ 25 января 2019

Эта проблема возникла сразу после попытки запустить мое приложение python flask в фоновом режиме, используя:

$python app.py &

Это сразу не удалось. После этого любые будущие попытки без проблем запустить приложение, которые я делал ранее, заканчивались выдачей этой ошибки:

 $ 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 <module>
    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__
    restore_signals, start_new_session)
  File "/usr/lib/python3.6/subprocess.py", line 1275, in _execute_child
    restore_signals, start_new_session, preexec_fn)
BlockingIOError: [Errno 11] Resource temporarily unavailable

Ошибка, по-видимому, связана с запуском в режиме разработчика, поскольку, когда я запускаю с app.run_server(debug=False) (кстати, util.DEBUG имеет значение True в моей локальной среде), приложение работает нормально, но тогда я не получить горячую перезагрузку, что важно для меня.

Я пытался перебазировать Cygwin согласно этому посту https://superuser.com/a/194537/276726,, но это ничего не исправило.

Я также пытался создать специальный файл rebase, следуя инструкциям в этом посте , но это тоже не помогло.

Приложение работает в режиме разработки из моей командной строки Windows, так что пока это мое временное исправление, но я бы хотел, чтобы моя установка Cygwin снова заработала правильно.

Спасибо за помощь!

1 Ответ

0 голосов
/ 03 февраля 2019

Вы сталкиваетесь с довольно распространенной проблемой в мире Cygwin . Многие URL упоминают (имеют дело) об этом, но я собираюсь перечислить те, с которыми я столкнулся:

  1. [SO]: ошибка Cygwin: «-bash: fork: retry: ресурс временно недоступен»
  2. [SO]: проблема Cygwin - невозможно переназначить; тот же адрес, что и у родителя
  3. [SuperUser]: фатальная ошибка Cygwin не может быть переназначена .. Что это значит?
  4. [WordPress]: Cygwin и Rails - невозможно переназначить на тот же адрес, что и родительский; умер в ожидании загрузки dll, errno 11
  5. [SO]: ошибка Cygwin: «child_info_fork :: abort: загружен по другому адресу:»

«Магия за кулисами» очень хорошо объяснена в [Cygwin]: проблемы с созданием процесса ( выделения мои):

Семантика fork требует, чтобы разветвленный дочерний процесс имел точно такую ​​же структуру адресного пространства, что и его родительский процесс. Однако Windows не обеспечивает встроенной поддержки клонирования адресного пространства между процессами , и некоторые функции активно подрывают надежную реализацию fork. Три проблемы особенно распространены:

  • Коллизии базовых адресов DLL. В отличие от общих библиотек * nix, которые используют «независимый от позиции код», общие библиотеки Windows принимают фиксированный базовый адрес. Всякий раз, когда сталкиваются жесткие диапазоны адресов двух библиотек DLL (что происходит довольно часто), загрузчик Windows должен «перебазировать» один из них на другой адрес. Однако он может не разрешать конфликты последовательно и может перебазировать другую DLL и / или перемещать ее по разному адресу каждый раз. Cygwin обычно может компенсировать этот эффект, когда он включает в себя динамически открываемые библиотеки, но коллизии между статически связанными dll (зависимостями, известными во время компиляции) разрешаются до инициализации cygwin1.dll и не могут быть впоследствии исправлены. Эту проблему можно решить только путем удаления конфликтов базовых адресов, которые вызывают проблему, обычно с помощью инструмента rebaseall .
  • Рандомизация размещения адресного пространства (ASLR). Начиная с Vista, Windows реализует ASLR, что означает, что стеки потоков, кучи, файлы с отображением в памяти и статически связанные библиотеки размещаются в разных (случайных) местах в каждом процессе. Такое поведение мешает правильному fork, и если неподвижный объект (куча процесса или системная DLL) оказывается в неправильном месте, Cygwin не может ничего сделать, чтобы компенсировать (хотя он будет повторяться несколько раз автоматически ).

Устранение неполадок выполняется в [Cygwin.FAQ]: 4.45. Как исправить ошибки fork ()? ( подчеркивает все еще мое). С риском спамить ответ, я собираюсь вставить его здесь:

К сожалению, Windows не использует модель создания процесса fork / exec, которая есть в UNIX-подобных ОС, поэтому Cygwin трудно реализовать надежный и правильный fork(), который может привести к сообщениям об ошибках, таких как:

  • невозможно переназначить somedll на тот же адрес, что и родительский
  • не удалось выделить кучу
  • умер в ожидании загрузки DLL
  • child -1 - умер в ожидании longjmp перед инициализацией
  • STATUS_ACCESS_VIOLATION
  • ресурс временно недоступен

Возможные решения для вышеуказанных ошибок:

  • Перезапустите любой процесс, который пытается (и не может) использовать fork(). Иногда Windows устанавливает рабочую среду, которая даже враждебнее fork(), чем обычно.
  • Убедитесь, что вы удалили (не просто отключили) все программное обеспечение на BLODA .
  • Переключитесь с 32-разрядного Cygwin на 64-разрядный Cygwin, если ваша ОС и процессор поддерживают это. С большим адресным пространством fork () с меньшей вероятностью потерпит неудачу.
  • Попробуйте установить для переменной среды CYGWIN значение «detect_bloda», что позволит выполнить дополнительную отладку, которая может указывать, какое другое программное обеспечение вызывает проблему.

    См. в этом письме для получения дополнительной информации.

  • Принудительная полная перебазировка: запустите триггер перебазирования полная перебазировка , закройте все программы Cygwin и запустите установку Cygwin .

    По умолчанию программа установки Cygwin автоматически выполняет пошаговую перебазку вновь установленных файлов.Принудительная полная перебазировка приводит к очистке карты перебазирования перед выполнением перебазировки.

    См. / usr / share / doc / rebase / README и / usr / share/doc/Cygwin/_autorebase.README для получения более подробной информации .

    Обратите внимание, что установка новых пакетов или обновление существующих отменяет эффекты rebase и часто вызывает повторное появление fork().

См. Раздел Создание процесса Руководства пользователя по техническим причинам, из-за которых трудно fork() работать надежно.

Чтобы воспроизвести проблему, я использовал:

  • Cygwin 32 :
    • Вероятность столкнуться с проблемой очень великавыше
    • Это не мой главный Cygwin env
  • Python 3.6.4 + VEnv
    • Расположен по адресу / home / cfati / Work / Dev / VEnvs / py_032_03.06.04_test0

Iпытался воспроизвести васточное поведение (с _lbfgsb * .dll ), но pip -v install scipy не удалось его построить.
Начиная с [SciPy]: установка SciPy в Windows описывает довольно сложный процесс, и у меня не было никакой гарантии, что в конце я смогу воспроизвести проблему, я попробовал с numpy 's .dll s ( numpy был успешно установлен как scipy зависимость), но я не смог (как сторонаВ результате import numpy загружает кучу .dll с), но вызов fork ( через subprocess.Popen) не завершился неудачей.
Затем я решил взять дело в свои руки и создать небольшую программу, которая загружает несколько .dll s, а затем разветвляется (снова через subprocess.Popen), чтобы сделать проблему воспроизводимой.насколько это возможно.

dll.c :

#include <stdio.h>

#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()

Примечания :

  • Сценарий немного другой, вместо модуля расширения Python , у меня есть обычный (фиктивный) .dll ,который я пытаюсь загрузить через [Python 3.Docs]: ctypes - библиотека сторонних функций для Python .Это не должно иметь никакого значения, так как Python не видит его (как модуль или как внешний .dll ) , ему все равно придется его загружать в процесс (так же)
  • Сценарий:
    • Я загружаю 2 таких .dll с (на самом деле это то же самое .dll скопированы под другим именем, поэтому они оба имеют одинаковый предпочитаемый базовый адрес ), поэтому 1 st .dll , вероятно, будетзагружается по этому адресу, в то время как следующий .dll будет загружен с другим
    • Затем я fork процесса, а в дочернем, на основе случайногофактор, я переключаю .dll порядок загрузки
    • Когда 2 nd .dll будет загружен на предпочтительной базе, там будетбыть несовместимым с родительским процессом, приводящим к ошибке
  • Сначала все было в моем cwd , затем (чтобы быть ближе к вашей проблеме) я создал Python пакет с файлами.Обратите внимание, что я сделал это неправильно (установка через файл setup.py ), но копировал вручную все
[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 <module>
    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__
    restore_signals, start_new_session)
  File "/usr/lib/python3.6/subprocess.py", line 1275, in _execute_child
    restore_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 <module>
    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__
    restore_signals, start_new_session)
  File "/usr/lib/python3.6/subprocess.py", line 1275, in _execute_child
    restore_signals, start_new_session, preexec_fn)
BlockingIOError: [Errno 11] Resource temporarily unavailable

Такошибка вполне воспроизводимая.Я также хотел бы добавить сюда детали .dll ( Зависимость Уокер ):

Img0

Почему обычная rebase ( rebaseall ) не решает проблему?

  • Пакеты Cygwin имеют скрипт постинсталляции, который вызывает rebase для их .dll s
  • rebase поиск в стандартных путях к библиотекам ( / lib , / usr / lib , ...).Это можно отрегулировать в соответствии с / usr / share / doc / Cygwin / _autorebase.README :

    Пакеты могут указывать потенциальные местоположения таких динамическихобъекты, известные путем удаления файла (названного по имени пакета) в / var / lib / rebase / dynpath.d / .Если какие-либо динамические объекты устанавливаются пользователями, эти местоположения должны быть объявлены в / var / lib / rebase / user.d / (имя файла должно совпадать с именем пользователя, если на нем несколько пользователейsystem)

    Python требует такой настройки, поскольку пакеты могут содержать .dll s

  • pip как у пакетов нет есть сценарий постустановки (который будет перебазировать их .dll s)
  • VEnv находится в домашний путь пользователя , который не в стандартных путях к библиотекам (поэтому даже rebaseall будет игнорировать их)

Обратите внимание, что все перебазированные .dll s хранятся в DB : / 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]>

Чтобы инструменты .dll были выбраны инструментами rebase , им нужныбыть рекламируемым.Это можно сделать двумя способами:

  • Укажите их в одном из пользовательских мест, поэтому при следующей полной перезагрузке они больше не будут игнорироваться (просто добавьте VEnv dir и другие, если есть):

    [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
    
  • Вручную перебазировать .dll s

Они оба работали для меня, но я собираюсь привести пример только для варианта 2 nd (как это проще).Процесс состоит из 2 шагов:

  • Создание списка всех .dll с, которые необходимо перебазировать

    [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
    
  • Выполнить ребазирование

    • Все процессы Cygwin должны быть закрыты (включая службы: например, sshd )
    • Я запустил команду с dash.exe (запускается непосредственно с Win , с Cygwin bin dir), и не из Mintty (обратите внимание на подсказку)
    $ /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
    ...
    

Обновленное окно Dependency Walker (отметьте Предпочитаемую базу и сравните его с изображением на предыдущем изображении):

Img1

А также rebase DB «запрос» (теперь вернулся из Mintty ):

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

Что важнее, запуск кода :

[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

Как видноможет разветвляться несколько раз (остановился только потому, что я нажал Enter ).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...