mod_wsgi 不允许子进程退出

mod_wsgi won't allow a child process to exit

我使用 CherryPy、Apache 和 mod_wsgi 构建了一个网站,除一个问题外,一切都很好。当用户操作要求自动发送电子邮件时,我有时会使用 os.fork 这样父进程可以立即 return 并给用户一个 "OK" 消息,而子进程是负责发送电子邮件(这可能需要几秒钟,我不希望用户必须等待)。

当子进程完成其工作并调用 sys.exit() 时,问题就出现了。似乎 mod_wsgi 捕获了 SystemExit 异常,将回溯转储到我的 Apache 错误日志中,并保留子进程 运行。我有两个问题:

  1. 它使 Apache 错误日志变得杂乱无章,回溯并不代表任何实际出错的地方,并且

  2. 离开进程运行,浪费系统资源。更糟糕的是,随着时间的推移,这些休眠进程中有多少会累积起来?

作为记录,Apache 错误日志中的输出如下所示:

mod_wsgi (pid=14900): SystemExit exception raised by WSGI script '/Users/me/myscript.py' ignored.

随后是 sys.exit() 调用之前的回溯。

我猜 this 解释了为什么 SystemExit 异常被 mod_wsgi 捕获,但这对我没有帮助。

如果有一种方法可以配置 mod_wsgi 在这方面的行为,那就太好了,但是当我在 [=17] 中同时搜索 "SystemExit" 和 "sys.exit" 时=],没有人发现任何东西。

在该站点上搜索 "mod_wsgi SystemExit" 只得到六个帖子,其中 none 询问如何允许子进程退出。

有谁知道如何让子进程真正退出,并使 mod_wsgi 不将任何内容转储到 Apache 错误日志中?

一般来说,您不应在托管在您未创建的服务器进程中的代码中使用 fork()。它通常会导致奇怪的流程生命周期问题,类似于您在此处描述的问题。 (这超出了 Apache、WSGI 或 Python;它适用于多种情况。)

如果可以的话,我建议使用单独的工作队列来处理异步任务。对于 Python,一个经常使用的选项是 Celery

如果那绝对不是一个选项,您可以绕过 SystemExit 异常并通过调用 os._exit() 在 Python 中立即退出。但是,请注意,这可能仍然会导致一些奇怪的行为,我不推荐这样做。