Когда процесс получает SIGTERM
, он должен завершиться и завершиться, выполнив как можно меньше операций и ничего не печатая.
Процесс werkzeug.serving.run_simple
получающий SIGTERM
обычно приводит к коду возврата 141 (симптом необработанного / неправильно обработанного SIGPIPE
), а при использовании перезагрузчика процесс становится зомби (он имеет быть убитым вручную, так как порт остается связанным).
Добавление обработчика сигнала для SIGTERM
который просто вызывает sys.exit(0)
, достаточно, чтобы исправить проблему (в том смысле, что больше нет неправильного поведения процесса), но я не уверен, что это действительно правильное исправление.
Теперь привязываю обработчик сигнала при запуске с перезагрузкой. Надеюсь, это поможет.
В какой версии это исправление? Это все еще проблема в Flask 0.8.
Это все еще проблема, это довольно раздражает при использовании Flask с IDE - всякий раз, когда вы прекращаете отладку, процесс сохраняется и продолжает обслуживать запросы.
Я снова открываю эту проблему, поскольку она, кажется, сохраняется, см. Следующее обсуждение сегодня в IRC.
20:20 < mcdonc> can somebody fix flask's reloader so when you send the process a sigint it actually stops the child process
20:20 < untitaker> mcdonc: it seems to work for me
20:21 < untitaker> mcdonc: it used to cause problems but for me it's fixed in latest master
20:21 < mcdonc> ah good. i just got some number of complaints from people who run it under supervisor.
20:22 < untitaker> mcdonc: you are talking about the one from the Py3 port?
20:22 < untitaker> released versions should work properly
20:22 < mcdonc> no.. i am talking about.. well.. yes, i dont actually know what i'm talking about ;-) i dont use it, i just get people telling me they need to send a stop signal to the entire process group instead of to the process to make sure its killed.
20:23 < mcdonc> this is not recent.. for the last year or so
20:23 < mcdonc> why people run the reloader under supervisor (presumably in production) i cannot fathom
20:23 < mcdonc> but they do
20:24 < Alex_Gaynor> mcdonc: I've toyed with using supervisord in dev, FWIW
20:24 < Alex_Gaynor> mcdonc: for cases where you don't just have web proc, you've also got background daemons and such, it could be nice
[...]
20:32 < DasIch> untitaker: the supervisor issue is independent from the threading/thread issue
20:32 < untitaker> DasIch: ah okay
20:32 < untitaker> didn't know that
20:32 < untitaker> DasIch: is the reloader behaving weird in supervisor?
20:33 < DasIch> untitaker: I guess what happens if you run the reloader in supervisor is that supervisor kill the reloading process but that doesn't kill the process started by the reloader
20:34 < untitaker> DasIch: couldn't one write a wrapper shell script that kills both?
20:34 < untitaker> at least for now
20:34 < DasIch> untitaker: I think you shouldn't use the reloader in production
20:35 < untitaker> well yeah
20:35 < asdf`> (supervisord has a 'kill as group' thing)
20:35 < DasIch> right there is that as well
20:35 < asdf`> (it even mentions the werkzeug reloader in the docs paragraph about it!)
20:36 < mcdonc> yes i put it there
20:37 < asdf`> (then you might want to fix it, because AFAIR it actually says 'flask', while the reloader is part of werkzeug. But i admit 'flask' is something more people will know)
20:37 < mcdonc> nobody reads docs anyway ;)
20:38 < DasIch> I just wanted to mention I don't care unless someone creates an issue with a valid use case for that but apparently this seems to be it https://github.com/mitsuhiko/werkzeug/issues/58
20:38 < mcdonc> like alex said, it's not entirely crazy to want to use the reloader under supervisor in dev, esp. if your app is reliant on other processes being started
20:39 < mcdonc> i actually dont run my own apps under supervisor, but that's because i don't use a reloader, i just press ctrl-c.. because i'm a savage
20:40 < DasIch> I do use the reloader but I tend to save so often with bad syntax that I end up restarting manually all the time
Думаю, это все еще актуально.
Выполнение os.kill(parent_id, signal.SIGTERM)
не убивает дочерние процессы.
Я тоже столкнулся с этой проблемой при переработке набора тестов для werkzeug.serving
. Я работал над этим, убивая всю группу процессов: https://github.com/mitsuhiko/werkzeug/blob/a00377315bbf02ec48fdad22c6bb08433fc1e9c1/tests/conftest.py#L158
Я столкнулся с той же проблемой во Flask в режиме отладки (use_debugger = True). Однако я вижу код возврата 0 для «родительского» процесса. Без включенного режима отладки SIGTERM работает нормально, и процесс завершается с кодом 143. Python 2.7.5.
Получил также эту ошибку, в моем случае docker stop
отправлял SIGTERM
на сервер с werkzeug (moto), но сервер проигнорировал его, а затем докер убил его с помощью SIGKILL
результате в ненулевой код выхода.
Обходной путь заключался в том, чтобы указать SIGINT
(Ctrl + C) в качестве предпочтительного сигнала остановки в Dockerfile ( STOPSIGNAL SIGINT
), после чего контейнеры полностью отключились.
У меня такая же проблема при запуске приложения Flask внутри Docker; однако STOPSIGNAL SIGINT
по-прежнему недостаточно, чтобы остановить контейнер. Мне нужно использовать SIGKILL
.
Я не могу воссоздать проблему. Я пробовал это с официальным контейнером Python с тегами 2.7 и 3.7. Я использовал следующий Dockerfile:
FROM python:2.7
WORKDIR /usr/src/app
RUN pip install click \
werkzeug \
sqlalchemy \
jinja2
COPY . .
RUN python manage-shorty.py initdb
ENTRYPOINT ["python"]
CMD ["manage-shorty.py", "runserver"]
И построил контейнер из Dockerfile в каталоге examples
с помощью команды:
docker build -t werkzeug-examples .
Затем я бы запустил контейнер в интерактивном режиме и отменил бы с помощью:
$ docker run -it --name werkzeug-example werkzeug-examples
* Running on http://localhost:5000/ (Press CTRL+C to quit)
* Restarting with stat
^C
Запуск docker ps
показал, что он завершился с 0
:
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8c708ea4ef77 werkzeug-examples "python manage-short…" About a minute ago Exited (0) 58 seconds ago werkzeug-example
Запуск контейнера и остановка с помощью docker stop werkzeug-example
также завершается с помощью 0
.
Вот результат версии Docker на компьютере, на котором я выполнил эти команды:
Client: Docker Engine - Community
Version: 18.09.2
API version: 1.39
Go version: go1.10.8
Git commit: 6247962
Built: Sun Feb 10 04:12:39 2019
OS/Arch: darwin/amd64
Experimental: false
Server: Docker Engine - Community
Engine:
Version: 18.09.2
API version: 1.39 (minimum version 1.12)
Go version: go1.10.6
Git commit: 6247962
Built: Sun Feb 10 04:13:06 2019
OS/Arch: linux/amd64
Experimental: false
Можете ли вы привести пример, который может воспроизвести проблему, с которой вы столкнулись?
Пока мы не получим воспроизводимый сценарий, я закрою его, поскольку он не может быть воспроизведен в последней версии Docker и Werkzeug.
Самый полезный комментарий
Получил также эту ошибку, в моем случае
docker stop
отправлялSIGTERM
на сервер с werkzeug (moto), но сервер проигнорировал его, а затем докер убил его с помощьюSIGKILL
результате в ненулевой код выхода.Обходной путь заключался в том, чтобы указать
SIGINT
(Ctrl + C) в качестве предпочтительного сигнала остановки в Dockerfile (STOPSIGNAL SIGINT
), после чего контейнеры полностью отключились.