当进程接收到SIGTERM
,它应关闭并退出,并进行尽可能少的操作且不打印任何内容。
werkzeug.serving.run_simple
进程收到SIGTERM
的返回码通常为141(未处理/错误处理的SIGPIPE
症状),并且在使用重新加载程序时,进程变为僵尸(由于端口保持绑定状态,需要手动杀死)。
为SIGTERM
添加一个仅调用sys.exit(0)
的信号处理程序就足以解决该问题(因为不会再有该过程的不当行为了),但是我不确定这实际上是正确的解决方法。
现在,当使用reloader运行时,我绑定了一个信号处理程序。 希望能有所帮助。
此修复程序是什么版本的? 在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 :
我在使用调试模式(use_debugger = True)的Flask中遇到了同样的问题。 但是,我在“父”进程上看到的返回码为0。 如果未启用调试模式,则SIGTERM可以正常工作,并且该过程以代码143退出。Python 2.7.5。
也遇到了这个错误,在我的情况下, docker stop
正在将SIGTERM
发送到由werkzeug驱动的服务器(moto),但是服务器忽略了,然后docker用SIGKILL
杀死了它变成非零的退出代码。
解决方法是在容器干净关闭之后,将SIGINT
(Ctrl + C)指定为Dockerfile( STOPSIGNAL SIGINT
)中的首选停止信号。
在Docker中运行Flask应用程序时,我遇到了同样的问题; 但是, STOPSIGNAL SIGINT
仍然不足以停止容器。 我必须使用SIGKILL
。
我无法重现该问题。 我已经使用带有2.7和3.7标签的官方Python容器尝试了此操作。 我使用了以下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),但是服务器忽略了,然后docker用SIGKILL
杀死了它变成非零的退出代码。解决方法是在容器干净关闭之后,将
SIGINT
(Ctrl + C)指定为Dockerfile(STOPSIGNAL SIGINT
)中的首选停止信号。