FastCgi 崩溃——想要捕获所有异常,但如何捕获?

发布于 2024-07-19 12:22:17 字数 3331 浏览 5 评论 0原文

我有一个使用 fastcgi 在 apache 上运行的 django 应用程序(使用 Flup 的 WSGIServer)。

这通过dispatch.fcgi 进行设置,连接如下:

#!/usr/bin/python

import sys, os

sys.path.insert(0, os.path.realpath('/usr/local/django_src/django'))

PROJECT_PATH=os.environ['PROJECT_PATH']

sys.path.insert(0, PROJECT_PATH)

os.chdir(PROJECT_PATH)

os.environ['DJANGO_SETTINGS_MODULE'] = "settings"

from django.core.servers.fastcgi import runfastcgi

runfastcgi(method="threaded",daemonize='false',)

runfastcgi 负责完成这项工作,最终在 WSGIHandler 上运行 WSGIServer。

有时会发生导致 fastcgi 崩溃的异常。

编辑:我不知道什么错误导致 fastcgi 崩溃,或者 fastcgi 是否崩溃。 我只知道有时网站会宕机——持续宕机——直到我重新启动 apache。 error.log 中出现的唯一错误是损坏的管道和不完整的标头,如下所列。

不完整的标题:

注意:我已用“...”替换了敏感信息或混乱 破损

[Sat May 09 ...] [error] [client ...] (104)Connection reset by peer: FastCGI: comm with server ".../dispatch.fcgi" aborted: read failed
[Sat May 09 ...] [error] [client ...] FastCGI: incomplete headers (0 bytes) received from server ".../dispatch.fcgi"
[Sat May 09 ...] [error] [client ...] (32)Broken pipe: FastCGI: comm with server ".../dispatch.fcgi" aborted: write failed,

的管道:

注意:这恰好是针对 trac 站点而不是 django 应用程序,但它看起来是一样的。

Unhandled exception in thread started by <bound method Connection.run of <trac.web._fcgi.Connection object at 0xb53d7c0c>>
Traceback (most recent call last):
  File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 654, in run
    self.process_input()
  File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 690, in process_input
    self._do_params(rec)
  File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 789, in _do_params
    self._start_request(req)
  File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 773, in _start_request
    req.run()
  File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 582, in run
    self._flush()
  File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 589, in _flush
    self.stdout.close()
  File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 348, in close
    self._conn.writeRecord(rec)
  File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 705, in writeRecord
    rec.write(self._sock)
  File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 542, in write
    self._sendall(sock, header)
  File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 520, in _sendall
    sent = sock.send(data)
socket.error: (32, 'Broken pipe')

我查看了 /var/log/apache2/error.log,但似乎找不到崩溃的原因。 我有时会遇到内存交换问题,但我认为这是不同的。 (请原谅我的无知。我愿意学习如何更好地实现和调试服务器管理内容。)

我想用 try/ except 包装 runfastcgi 。 处理随机异常的最佳方法是什么(直到我找出实际原因)?

我相信 WSGIServer 可以处理很多请求。 如果我捕获异常,我可以重新调用 runfastcgi 而不必担心无限循环吗? 我应该为有问题的异常调用请求返回 Error HttpRequest 吗? 我什至不知道该怎么做。

我一直在浏览 django/core/servers/fastcgi.py 和 django/core/handlers/wsgi.py 和 django/http/init.py

我一直无法取得进展理解事情的一面。

有我可以借鉴的想法或经验吗?

谢谢!

I have a django app running on apache with fastcgi (uses Flup's WSGIServer).

This gets setup via dispatch.fcgi, concatenated below:

#!/usr/bin/python

import sys, os

sys.path.insert(0, os.path.realpath('/usr/local/django_src/django'))

PROJECT_PATH=os.environ['PROJECT_PATH']

sys.path.insert(0, PROJECT_PATH)

os.chdir(PROJECT_PATH)

os.environ['DJANGO_SETTINGS_MODULE'] = "settings"

from django.core.servers.fastcgi import runfastcgi

runfastcgi(method="threaded",daemonize='false',)

The runfastcgi is the one that does the work, eventually running a WSGIServer on a WSGIHandler.

Sometimes an exception happens which crashes fastcgi.

EDIT: I don't know what error crashes fastcgi, or whether fastcgi even crashes. I just know that sometimes the site goes down--consistently down--until I reboot apache. THe only errors that appear in the error.log are the broken pipe and incomplete headers ones, listed below.

Incomplete headers:

note: I've replaced sensitive information or clutter with "..."

[Sat May 09 ...] [error] [client ...] (104)Connection reset by peer: FastCGI: comm with server ".../dispatch.fcgi" aborted: read failed
[Sat May 09 ...] [error] [client ...] FastCGI: incomplete headers (0 bytes) received from server ".../dispatch.fcgi"
[Sat May 09 ...] [error] [client ...] (32)Broken pipe: FastCGI: comm with server ".../dispatch.fcgi" aborted: write failed,

Broken pipe:

note: this happens to be for a trac site not a django app, but it looks the same.

Unhandled exception in thread started by <bound method Connection.run of <trac.web._fcgi.Connection object at 0xb53d7c0c>>
Traceback (most recent call last):
  File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 654, in run
    self.process_input()
  File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 690, in process_input
    self._do_params(rec)
  File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 789, in _do_params
    self._start_request(req)
  File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 773, in _start_request
    req.run()
  File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 582, in run
    self._flush()
  File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 589, in _flush
    self.stdout.close()
  File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 348, in close
    self._conn.writeRecord(rec)
  File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 705, in writeRecord
    rec.write(self._sock)
  File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 542, in write
    self._sendall(sock, header)
  File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 520, in _sendall
    sent = sock.send(data)
socket.error: (32, 'Broken pipe')

I've looked through /var/log/apache2/error.log, but I can't seem to find the cause of the crashing. I sometimes have memory swapping problems, but I think this is different. (Please excuse my ignorance. I am willing to learn how to implement and debug server admin stuff better.)

I'd like to wrap the the runfastcgi with a try/except. What is the best way to handle random exceptions (until I figure out the actual cause(s))?

I believe the WSGIServer handles many requests. If I catch an exception, can I re-call runfastcgi without fear of an infinite loop? Should I return an Error HttpRequest for the offending, exception-calling request? I'm not even sure how to do that.

I've been looking through django/core/servers/fastcgi.py and django/core/handlers/wsgi.py and django/http/init.py

I haven't been able to make progress understanding flup's side of things.

Have ideas or experiences I might learn from?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

穿透光 2024-07-26 12:22:17

这可能是 Flup bug。 当基于 flup 的服务器的客户端连接在 flup 完成发送数据之前关闭时,它会引发 socket.error: (32, 'Broken pipeline') 异常。

尝试通过 runfastcgi 周围的 try catch 来捕获异常是行不通的。 很简单,因为异常是由线程引发的。

好的,我将解释为什么将您自己的代码包装在 try catch 中不起作用。 如果仔细查看异常回溯,您会发现跟踪中的第一个语句不是 runfastcgi。 那是因为异常发生在不同的线程中。 如果你想捕获异常,你需要将跟踪列出的任何语句包装在 try/catch 中,如下所示:

# in file /usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 654, in run
try:
    self.process_input()
except socket.error:
    # ignore or print an error
    pass

重点是,你可以通过修改 Flup 的代码来捕获错误。 但我看不出这有什么好处。 特别是因为这个异常似乎是无害的,并且已经有一个补丁。

This is probably a Flup bug. When a flup-based server's client connection is closed before flup is done sending data, it raises a socket.error: (32, 'Broken pipe') exception.

Trying to catch the exception by a try catch around runfastcgi will not work. Simply because the exception is raised by a thread.

OK, I'll explain why the wrapping your own code in a try catch won't work. If you look closely at the exception traceback you'll see that the first statement in the trace is not runfastcgi. That's because the exception is happening in a different thread. If you want to catch the exception you need to wrap any of the statements listed by the trace in a try/catch like this:

# in file /usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 654, in run
try:
    self.process_input()
except socket.error:
    # ignore or print an error
    pass

The point is, you can catch the error by modifing Flup's code. But I don't see any benefit from this. Especial because this exception seems to be harmless and there already is a patch for it.

霞映澄塘 2024-07-26 12:22:17

管道破裂通常不是确定性的。 如果管道或套接字上的写入操作因另一端关闭了连接而失败,则会出现“管道损坏”的情况。 因此,如果您的 FastCGI 出现管道损坏,则意味着网络服务器过早关闭了连接。 在某些情况下这不是问题,可以默默地忽略它。

作为一个快速技巧,尝试捕获并忽略带有 Broken pipelinesocket.error。 您可能需要在更多地方添加 except: 子句。

Broken pipe usually doesn't come deterministically. You get a Broken pipe if a write operation on a pipe or socket fails because the other end has closed the connection. So if your FastCGI gets a Broken pipe, it means that the webserver has closed to connection too early. In some cases this is not an problem, it can be ignored silently.

As a quick hack, try to catch and ignore the socket.error with Broken pipe. You may have to add an except: clause to many more places.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文