Werkzeug: 写入封闭管道后 Werkzeug 崩溃

创建于 2016-06-20  ·  41评论  ·  资料来源: pallets/werkzeug

我有一个在 NGINX 后面运行的 Werkzeug 服务器。 当客户端在等待 Werkzeug 服务器响应时断开连接,NGINX 会关闭通往 Werkzeug 的管道。 当python程序将响应写入Werkzeug时,出现如下异常,Werkzeug崩溃:

回溯(最近一次调用最后一次):
文件“server.py”,第 81 行,在
app.run(host=args.host, port=args.port, debug=False)
运行中的文件“/usr/local/lib/python2.7/dist-packages/flask/app.py”,第 843 行
run_simple(主机,端口,自我,**选项)
文件“/usr/local/lib/python2.7/dist-packages/werkzeug/serving.py”,第 694 行,在 run_simple 中
内()
文件“/usr/local/lib/python2.7/dist-packages/werkzeug/serving.py”,第659行,在内部
srv.serve_forever()
文件“/usr/local/lib/python2.7/dist-packages/werkzeug/serving.py”,第499行,在serve_forever
HTTPServer.serve_forever(self)
文件“/usr/lib/python2.7/SocketServer.py”,第 238 行,在 serve_forever 中
self._handle_request_noblock()
文件“/usr/lib/python2.7/SocketServer.py”,第 297 行,在 _handle_request_noblock 中
self.handle_error(请求,client_address)
文件“/usr/lib/python2.7/SocketServer.py”,第 295 行,在 _handle_request_noblock 中
self.process_request(请求,client_address)
文件“/usr/lib/python2.7/SocketServer.py”,第 321 行,在 process_request 中
self.finish_request(请求,client_address)
文件“/usr/lib/python2.7/SocketServer.py”,第334行,在finish_request中
self.RequestHandlerClass(request, client_address, self)
文件“/usr/lib/python2.7/SocketServer.py”,第 651 行,在 init 中
self.finish()
文件“/usr/lib/python2.7/SocketServer.py”,第710行,完成
self.wfile.close()
文件“/usr/lib/python2.7/socket.py”,第 279 行,关闭
self.flush()
文件“/usr/lib/python2.7/socket.py”,第 303 行,齐平
self._sock.sendall(视图[write_offset:write_offset+buffer_size])
socket.error: [Errno 32] 断管

我是否缺少一些配置选项以防止它崩溃? 通常所有异常都会被捕获并返回 500 错误,服务器保持活动状态。

最有用的评论

在最近的修复提交的指导下,我已经能够通过使用 passthrough_errors=False 调用 app.run 来解决这个问题。 青年会

所有41条评论

使用生产 WSGI 服务器,例如 Gunicorn 或 uWSGI,而不是 Werkzeug 开发服务器。

我有一个非常相似的问题,除了我使用 Werkzeug 开发服务器进行开发(即 AFAICT,它的预期用途),即浏览器直接连接到端口 5000。

该错误每小时发生数次,迫使服务器手动重启以继续开发。

这是一个追溯:

Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 801, in __bootstrap_inner
    self.run()
  File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 754, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/Users/fermigier/envs/extranet-spr/lib/python2.7/site-packages/werkzeug/serving.py", line 659, in inner
    srv.serve_forever()
  File "/Users/fermigier/envs/extranet-spr/lib/python2.7/site-packages/werkzeug/serving.py", line 499, in serve_forever
    HTTPServer.serve_forever(self)
  File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 238, in serve_forever
    self._handle_request_noblock()
  File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 297, in _handle_request_noblock
    self.handle_error(request, client_address)
  File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 295, in _handle_request_noblock
    self.process_request(request, client_address)
  File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 321, in process_request
    self.finish_request(request, client_address)
  File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 334, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 655, in __init__
    self.handle()
  File "/Users/fermigier/envs/extranet-spr/lib/python2.7/site-packages/werkzeug/serving.py", line 216, in handle
    rv = BaseHTTPRequestHandler.handle(self)
  File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/BaseHTTPServer.py", line 340, in handle
    self.handle_one_request()
  File "/Users/fermigier/envs/extranet-spr/lib/python2.7/site-packages/werkzeug/serving.py", line 251, in handle_one_request
    return self.run_wsgi()
  File "/Users/fermigier/envs/extranet-spr/lib/python2.7/site-packages/werkzeug/serving.py", line 193, in run_wsgi
    execute(self.server.app)
  File "/Users/fermigier/envs/extranet-spr/lib/python2.7/site-packages/werkzeug/serving.py", line 186, in execute
    write(b'')
  File "/Users/fermigier/envs/extranet-spr/lib/python2.7/site-packages/werkzeug/serving.py", line 152, in write
    self.send_header(key, value)
  File "/usr/local/Cellar/python/2.7.11/Frameworks/Python.framework/Versions/2.7/lib/python2.7/BaseHTTPServer.py", line 401, in send_header
    self.wfile.write("%s: %s\r\n" % (keyword, value))
IOError: [Errno 32] Broken pipe

我在开发服务器 ( debug=True ) 上遇到了与@sfermigier完全相同的问题,并且有相同的回溯错误。

这种行为通常发生在一个非常简单的情况下:您正在使用某种自动完成功能。 浏览器为查询令牌启动一个连接,然后停止并启动另一个对更多令牌的请求。 你最终会得到很多破碎的管道。 直到上次发布这才成为
因此,建议使用功能齐全的应用程序服务器是一个很好的解决方法,但我仍然在这里看到一个问题。 当然,这是一个仅限开发的问题,但触发如此普遍的事实使得许多不习惯 _protocol internals_ 的开发人员感到不安。
损坏的管道很常见(想想一个很长的错误请求和开发人员点击浏览器停止按钮)并且不应该破坏开发服务器。
只是我的观点。 :)

@xcash

这种行为通常发生在一个非常简单的情况下:您正在使用某种自动完成功能。 浏览器为查询令牌启动一个连接,然后停止并启动另一个对更多令牌的请求。

如果它相关,我可以确认我使用browsersyncgulp.js遇到了这个问题。

有没有人有不包括运行 WSGI 服务器的解决方案? 我似乎遇到了机器人对我的主机执行 SYN 扫描的问题。

@glennzw你能更具体地说明你的环境吗? 你不应该在机器人可以访问的开放网络上公开你的开发服务器。 :) 在这种情况下,就像客户端的演示主机一样,最好至少使用一个真正的应用程序服务器,比如 gunicorn,它的占用空间非常小。

FWIW,我一直没有跟上发布的多少,这个(非常烦人的)问题在 2016 年 5 月至 8 月之间的某个时间开始发生在我身上,我可以说是最好的。 我将它添加到我的 setup.py install_requires = ['Werkzeug<0.11', 'flask<0.11', ... - 这似乎解决了这个问题(IME,只是固定 Werkzeug 似乎没有解决问题?)

对我来说,重复案例很简单——加载一个页面,但不要让它完成加载。 也就是说,只要触发 _any_ 损坏的管道错误 - 网络服务器就会崩溃并且无法为任何其他请求提供服务。 恕我直言,当客户端过早关闭连接时,网络服务器不能_摔倒_ - 即使是开发人员。

难道你们都在某处设置了passthrough_errors吗?

@untitaker在这种情况下,托盘/烧瓶#1674 托盘/烧瓶#1679 托盘/烧瓶#1928 可能相关吗?

我不知道,我想请一位记者确认一下。

2016年8月26日17时05分25秒CEST,大卫主[email protected]写道:

@untitaker在这种情况下,托盘/烧瓶#1674 托盘/烧瓶#1679
托盘/烧瓶#1928 可能相关?

你收到这个是因为你被提到了。
直接回复此邮件或在 GitHub 上查看:
https://github.com/pallets/werkzeug/issues/954#issuecomment -242761250

使用 K-9 邮件从我的 Android 设备发送。 请原谅我的简短。

抄送@miguelgrinberg

我认为 Werkzeug 应该处理损坏的管道和连接重置错误。 这些真的不是错误的迹象,客户端只是走了。 在这种情况下,似乎应该引发一个特殊的异常,即使设置了错误传递,上面的全能方法也将其识别为要忽略的异常。

这是 gunicorn 的做法: https :

这就是它应该做的。 我想弄清楚如何重现
这种行为,但还没有明确的测试用例可用。 因此问题
关于passthrough_errors

我怀疑这不是 Werkzeug 中的错误,并且用户的浏览器
只是有一个仍然打开的连接阻止其他请求(而不是
服务器崩溃)。 如果您关闭浏览器并重新打开,服务器应该
再次发挥作用。

2016 年 8 月 26 日星期五上午 11:54:16 -0700,Miguel Grinberg 写道:

我认为 Werkzeug 应该处理损坏的管道和连接重置错误。 这些真的不是错误的迹象,客户端只是走了。 在这种情况下,似乎应该引发一个特殊的异常,即使设置了错误传递,上面的全能方法也将其识别为要忽略的异常。

这是 gunicorn 的做法: https :

你收到这个是因为你被提到了。
直接回复此邮件或在 GitHub 上查看:
https://github.com/pallets/werkzeug/issues/954#issuecomment -242821084

哦,显示管道损坏错误 _are_,是的,但他们不应该像描述的那样挂断服务器。 有关可能的原因,请参阅之前的评论。

我再次测试了最新的位,我仍然在我的环境中看到相同的行为。 但是由于您似乎无法复制,我试图找出为什么我很特别。

import time
from flask import Flask
app = Flask(__name__)


@app.route('/')
def hello_world():
    time.sleep(5)
    return 'Hello, World!'


if __name__ == "__main__":
    app.run()

它按预期使用flask run但是如果您在通过python hello.py启动响应之前关闭 Web 浏览器,Web 服务器会崩溃

您的部分回复似乎丢失了。

在 2016 年 8 月 26 日星期五下午 12:29:39 -0700,clayg 写道:

我再次测试了最新的位,我仍然在我的环境中看到相同的行为。 但是由于您似乎无法复制,我试图找出为什么我很特别。

You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub:
https://github.com/pallets/werkzeug/issues/954#issuecomment-242829536

是的,在 slack 三重勾中是你如何阻止引用和ctrl-return是你如何换行
在 github 上,triple-ticks 是您阻止引用的方式,但ctrl-return是您提交的方式
......无论如何......肌肉记忆

我在提交完成后立即编辑了我的帖子 - 我只是回应,因为看起来你是通过电子邮件回复的,我不确定 github 会在我编辑后向你发送另一条通知。

我无法通过上面的@clayg进行睡眠测试来

我还使用我的 Flask 视频流示例尝试了相同的技巧,该示例使用流响应在永无止境的流中提供视频帧,即使对于那个,我也可以关闭浏览器并且请求结束而不会出现任何错误。 这个很奇怪,因为我过去确信这个应用程序会在结束请求之前触发到控制台的管道损坏错误。

其实我说得太早了。 使用 Python 2.7 时,我每次都可以使用我的视频流应用程序进行重现。 我无法在 3.5 上重现。 上面的所有堆栈跟踪都是针对 2.7 的,因此如果您使用 Python 3 进行测试,请记住这一点。

一个更有趣的数据点。 如果使用重载器运行,当子进程退出时,运行重载器的主进程会启动另一个,因此不会中断。 但是,如果您在没有重新加载器的情况下运行服务器,则管道损坏错误会将您带回控制台。

编辑:忽略重新加载器启动另一个进程部分,这似乎没有发生,相反,我可能看到了更改直通错误设置的效果。

好的,这是对我认为正在发生的事情的分析:

  • 客户端在请求中途离开
  • 请求继续进行。 套接字连接似乎已缓冲,因此在大多数情况下,写入套接字不会引起任何问题。
  • 一旦请求结束,套接字服务器类将在套接字上发出flush() 。 这是当前已修复的 Python 库中一个旧错误的主题: http : socket.error并忽略它。
  • 然后套接字服务器尝试关闭连接。 这是以下堆栈帧,来自 OP 的回溯:

File "/usr/lib/python2.7/SocketServer.py", line 710, in finish self.wfile.close()

  • 不幸的是,在 Python 2.7 中, socket.close()方法所做的第一件事就是再次刷新:

File "/usr/lib/python2.7/socket.py", line 279, in close self.flush()

  • 第二次刷新尝试不受 try/except 保护,因此会引发 EPIPE 异常。
  • 套接字服务器捕获异常,然后将其传递给服务器的handle_error()方法。
  • handle_error()的 Werkzeug 实现查看passthrough_errors设置,并且由于我们始终将其设置为True ,因此重新引发 EPIPE 错误并让它冒泡到最佳。

Python 3 上的套接字代码完全不同,特别是,它似乎没有任何没有 try/excepts 的刷新调用。 在使用 Python 3 时,EPIPE 错误甚至不会冒泡到 Werkzeug。

我们甚至将 passthrough_errors 设置为 true 吗? 在 Werkzeug 中,它默认为 false。

2016年8月27日2时10分十三秒CEST,米格尔·格林贝格[email protected]写道:

好的,这是对我认为正在发生的事情的分析:

  • 客户端在请求中途离开
  • 请求继续进行。 套接字连接似乎是
    缓冲,因此在大多数情况下,写入套接字不会导致任何
    问题。
  • 一旦请求结束,套接字服务器类将发出flush()
    在插座上。 这是 Python 库中一个旧错误的主题
    目前已修复: http :
    此修复程序中的解决方案是捕获socket.error并忽略它。
  • 然后套接字服务器尝试关闭连接。 这是
    以下堆栈帧,来自 OP 的回溯:
 File "/usr/lib/python2.7/SocketServer.py", line 710, in finish
 self.wfile.close()

  • 不幸的是,在 Python 2.7 中,第一件事是socket.close()
    方法确实是再次刷新:
 File "/usr/lib/python2.7/socket.py", line 279, in close
 self.flush()

  • 第二次刷新尝试不受 try/except 保护,因此
    它引发了 EPIPE 异常。
  • 套接字服务器捕获异常,然后将其传递给
    服务器的handle_error()方法。
  • handle_error()的 Werkzeug 实现着眼于
    passthrough_errors设置,并且由于我们始终将其设置为
    True ,重新引发 EPIPE 错误并让它冒泡到顶部。

Python 3 上的套接字代码完全不同,特别是,
在没有 try/excepts 的情况下,它似乎没有任何刷新调用
他们。 使用时 EPIPE 错误甚至不会冒泡到 Werkzeug
蟒蛇 3.

你收到这个是因为你被提到了。
直接回复此邮件或在 GitHub 上查看:
https://github.com/pallets/werkzeug/issues/954#issuecomment -242881523

使用 K-9 邮件从我的 Android 设备发送。 请原谅我的简短。

哦,咳咳: https :

我认为passthrough_errors应该依赖于app.debug NVM,没用

除了实际上恢复该 PR 之外,我看不到其他选择。 passthrough_errors=True只是做它应该做的事情,如果没有将调试器附加到程序,这不是一个好的默认行为。

没关系,我找到了另一种方法。 两个 PR:

由于两者都是广义上的行为变化,我宁愿不向后移植它们。

我认为https://github.com/pallets/flask/pull/1996是一个可以接受的解决方案。 重要的是它修复了您不希望传播异常的常见情况。 如果您确实想要传播,那么您正在调试,在这种情况下,传播不应该传播的 socket.error 并不是什么大问题。

https://github.com/pallets/werkzeug/pull/998修复虽然不是很好。 应用程序可能会从它自己的处理程序中对套接字执行的某些操作合法地引发这些异常,并且这些异常也会被静音。 理想的解决方案是在它们发生的地方捕获它们,然后将其重新提升为handle_error可以识别和忽略的某个自定义异常类。 鉴于我们可能不想改变或超载SocketServer ,我认为我的投票是保留这部分原样。 您将把 EPIPE 转储到控制台,但仅在 Python 2 上,并且至少在其他修复程序进入后它不会停止服务器。它是无害的,这是过去存在的行为,在我制作之前passthrough_errors变化。

您描述的行为仅在启用 PASSTHROUGH_ERRORS 时发生。 否则从 Flask 中捕获异常。

不过,我想这种美容改进不值得。

2016年8月27日18时29分三十○秒CEST,米格尔·格林贝格[email protected]写道:

我认为https://github.com/pallets/flask/pull/1996是可以接受的
解决方案。 重要的是它解决了常见的情况
您不希望传播异常。 如果你想传播,
那么你正在调试,在这种情况下得到 socket.error
在不应该传播的时候传播并不是什么大问题。

https://github.com/pallets/werkzeug/pull/998修复不是很好
尽管。 应用程序可能会合法地引发这些异常
它在自己的处理程序中用套接字做的事情,那些会
也要保持沉默。 理想的解决方案是抓住这些
在它们发生的地方,然后作为一些自定义异常重新提出
handle_error可以识别和忽略的类。 鉴于我们
可能不想改变或重载SocketServer ,我想我的
投票是将这部分保留原样。 你会得到 EPIPE 转储到
控制台,但仅限于 Python 2,至少它不会停止
其他修复后的服务器进入。它是无害的,而且是一个
过去存在的行为,在我做出
passthrough_errors变化。

你收到这个是因为你被提到了。
直接回复此邮件或在 GitHub 上查看:
https://github.com/pallets/werkzeug/issues/954#issuecomment -242926832

使用 K-9 邮件从我的 Android 设备发送。 请原谅我的简短。

固定在主人。

您描述的行为仅在启用 PASSTHROUGH_ERRORS 时发生

是的,我省略了那个细节。 但这种变化甚至会影响 Python 3,在 Python 3 中这些都不是问题。 在 Py3 上,启用传递错误后,应用程序引发的合法 socket.error 将被静音。

高手好像wfm,期待下一个版本,谢谢!

嗨,我使用在 NGINX 后面运行的 Werkzeug 开发服务器,我面临同样的问题,谁能帮我解决这个问题,
11:13:11 web.1 | 127.0.0.1 - - [15/Sep/2016 11:13:11] "GET /api/method/frappe.utils.print_format.download_pdf?doctype=Purchase%20Order&name=PO-00001&format=PO&no_letterhead=0 HTTP/1.1" 200 - 11:13:11 web.1 | Error on request: 11:13:11 web.1 | Traceback (most recent call last): 11:13:11 web.1 | File "/home/ommi/frappe-bench/env/lib/python2.7/site-packages/werkzeug/serving.py", line 193, in run_wsgi 11:13:11 web.1 | execute(self.server.app) 11:13:11 web.1 | File "/home/ommi/frappe-bench/env/lib/python2.7/site-packages/werkzeug/serving.py", line 184, in execute 11:13:11 web.1 | write(data) 11:13:11 web.1 | File "/home/ommi/frappe-bench/env/lib/python2.7/site-packages/werkzeug/serving.py", line 152, in write 11:13:11 web.1 | self.send_header(key, value) 11:13:11 web.1 | File "/usr/lib/python2.7/BaseHTTPServer.py", line 401, in send_header 11:13:11 web.1 | self.wfile.write("%s: %s\r\n" % (keyword, value)) 11:13:11 web.1 | IOError: [Errno 32] Broken pipe

请帮忙

Ragav 使用另一个应用程序服务器而不是 werkzeug 的内置开发
服务器,如 gunicorn。 这是目前唯一的解决方案。

2016-09-15 8:07 GMT+02:00 Ragav [email protected]

嗨,我使用运行在 NGINX 后面的 Werkzeug 开发服务器,我面临着
同样的问题谁能帮我解决这个问题,```
11:13:11 web.1 | 127.0.0.1 - - [15/Sep/2016 11:13:11]“获取
/api/method/frappe.utils.print_format.download_pdf?
doctype=Purchase%20Order&name=PO-00001&format=PO&no_letterhead=0
HTTP/1.1" 200 -
11:13:11 web.1 | 请求时出错:
11:13:11 web.1 | 回溯(最近一次调用最后一次):
11:13:11 web.1 | 文件“/home/ommi/frappe-bench/env/
lib/python2.7/site-packages/werkzeug/serving.py”,第 193 行,在 run_wsgi 中
11:13:11 web.1 | 执行(self.server.app)
11:13:11 web.1 | 文件“/home/ommi/frappe-bench/env/
lib/python2.7/site-packages/werkzeug/serving.py”,第 184 行,在执行中
11:13:11 web.1 | 写(数据)
11:13:11 web.1 | 文件“/home/ommi/frappe-bench/env/
lib/python2.7/site-packages/werkzeug/serving.py”,第 152 行,写入
11:13:11 web.1 | self.send_header(键,值)
11:13:11 web.1 | 文件“/usr/lib/python2.7/BaseHTTPServer.py”,第401行,
在 send_header 中
11:13:11 web.1 | self.wfile.write("%s: %s\r\n" % (keyword, value))
11:13:11 web.1 | IOError: [Errno 32] 管道损坏

请帮忙


你收到这个是因为你被提到了。
直接回复本邮件,在GitHub上查看
https://github.com/pallets/werkzeug/issues/954#issuecomment -247243400,
或静音线程
https://github.com/notifications/unsubscribe-auth/AA6MZ6DNiRIfL91CLeYOoA70W9_nQQzGks5qqOCMgaJpZM4I58cy
.

在最近的修复提交的指导下,我已经能够通过使用 passthrough_errors=False 调用 app.run 来解决这个问题。 青年会

导致崩溃的错误已在 0.12 版中修复,于 2016 年 12 月 21 日发布。

  • 还原导致开发服务器崩溃的行为更改,而不是返回内部服务器错误(拉取请求 #2006)。

0.12 版上周才发布。

在 2017 年 3 月 20 日星期一上午 09:05:00 -0700,Alan Rotman 写道:

导致崩溃的错误已在 0.12 版中修复,于 2016 年 12 月 21 日发布。

  • 还原导致开发服务器崩溃的行为更改,而不是返回内部服务器错误(拉取请求 #2006)。

——
您收到此消息是因为您修改了打开/关闭状态。
直接回复此邮件或在 GitHub 上查看:
https://github.com/pallets/werkzeug/issues/954#issuecomment -287807602

今天刚看到ReleaseNotes,等这个修复已经很久了。

看: http :
版本 0.12
于 2016 年 12 月 21 日发布,代号 Punsch。

https://pypi.python.org/pypi/Flask/0.12
按大小上传的文件类型 Py 版本
Flask-0.12-py2.py3-none-any.whl (md5) Python Wheel 2.7 2016-12-21 80KB
Flask-0.12.tar.gz (md5) 来源 2016-12-21 519KB

啊,是的,你是说 Flask。 当然。

在 2017 年 3 月 20 日星期一上午 09:22:15 -0700,Alan Rotman 写道:

今天刚看到ReleaseNotes,等这个修复已经很久了。

看: http :
版本 0.12
于 2016 年 12 月 21 日发布,代号 Punsch。

https://pypi.python.org/pypi/Flask/0.12
按大小上传的文件类型 Py 版本
Flask-0.12-py2.py3-none-any.whl (md5) Python Wheel 2.7 2016-12-21 80KB
Flask-0.12.tar.gz (md5) 来源 2016-12-21 519KB

——
您收到此消息是因为您修改了打开/关闭状态。
直接回复此邮件或在 GitHub 上查看:
https://github.com/pallets/werkzeug/issues/954#issuecomment -287813405

对于在 threaded=True 模式下在 werkzeug 上运行 Flask 0.12.2 时遇到此问题的任何人,请注意:
在线程模式下,默认情况下,似乎每个 werkzeug 线程实际上仍然存在此问题,即如果您请求需要一些时间返回的路由,然后关闭来自客户端的连接,则该特定 werkzeug 会记录一个 IOError Broken Pipe 然后死了。 服务器整体继续运行,除了在我的应用程序中,我发现这以某种方式导致内存泄漏,在任何线程中的管道损坏后,烧瓶进程缓慢增长,用完所有 RAM,然后使用 SWAP,然后最终被被操作系统杀死。
在 app.run 中显式发送 passthrough_errors=False 似乎已经解决了这个问题 - 当客户端断开连接时线程不再死,它们优雅地记录 IOError 然后也记录这个(我从未在没有明确设置 passthrough_errors=False 的情况下看到过):

Exception happened during processing of request from ('127.0.0.1', 50652)
----------------------------------------

然后服务器继续正常运行。 我仍然需要等待几个小时才能看到内存泄漏是否再次出现,但我希望它不会出现。

以防万一这对任何人都有帮助。

我在 Ubuntu VM 上的 Kubernetes 上的 Ubuntu Docker 容器中也看到了这个错误:

Error on request:
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/werkzeug/serving.py", line 270, in run_wsgi
    execute(self.server.app)
  File "/usr/local/lib/python2.7/dist-packages/werkzeug/serving.py", line 261, in execute
    write(data)
  File "/usr/local/lib/python2.7/dist-packages/werkzeug/serving.py", line 227, in write
    self.send_header(key, value)
  File "/usr/lib/python2.7/BaseHTTPServer.py", line 412, in send_header
    self.wfile.write("%s: %s\r\n" % (keyword, value))
IOError: [Errno 32] Broken pipe

我创建了一个全新的 Ubuntu xenial VM 并在 Kubernetes 上的 Ubuntu Docker 容器中运行相同的代码,并且没有看到这个错误并且 Python Flask 按预期工作。 我认为这是我的主机(Ubuntu VM)的问题。

@vhosakot你能告诉我你是如何设置你的应用程序配置的吗? 我在与您相同的环境中遇到了类似的问题。

在路由函数中,我使用了另一个用于路由的函数。
我从该函数的响应中获取了数据。
现在,当我对该数据使用 _loads()_ 时,出现错误。

...
response = get_contents().data
        if response:
            data = loads(response)
..

错误: IOError: [Errno 32] Broken pipe

此页面是否有帮助?
0 / 5 - 0 等级