我有一个使用Python(2.7)编写的Web服务器,它使用Popen
将一些工作委托给子进程:
url_arg = "http://localhost/index.html?someparam=somevalue"
call = ('phantomjs', 'some/phantom/script.js', url_arg)
imageB64data = tempfile.TemporaryFile()
errordata = tempfile.TemporaryFile()
p = Popen(call, stdout=imageB64data, stderr=errordata, stdin=PIPE)
p.communicate(input="")
我发现有间歇性问题,大约在执行了一定数量的
Popen
后(大约为 64),进程会用尽文件描述符而无法正常工作——完全无响应,如果线程尝试打开任何文件或套接字,则所有线程似乎都会永久阻塞。
(可能相关:子进程 phantomjs
加载一个 URL 并回调到生成它的服务器。)
根据 此 Python bug 报告,我认为我需要在服务器进程内的所有 Popen
调用上设置 close_fds=True
,以减轻文件描述符泄漏。然而,我对围绕 exec
子进程和文件描述符继承的机制并不熟悉,因此 Popen
文档和前面提到的 bug 报告中的注释对我来说不太清楚。
听起来实际上会关闭我的进程中所有打开的文件描述符(包括活动请求套接字、日志文件句柄等),然后再执行子进程。这听起来比泄漏套接字要好得多,但仍会导致错误。
然而,在实践中,当我在Web请求期间使用close_fds=True
时,它似乎运行良好,到目前为止我尚未能够构建一个场景,在这种情况下它实际上会关闭任何其他请求套接字、数据库请求等。文档说明如下:
如果close_fds为true,则在执行子进程之前,所有文件描述符(除了0、1和2)都将关闭。
因此,我的问题是:在多线程Python Web服务器中,在调用
Popen
时传递close_fds=True
是否“安全”和“正确”?或者,如果其他请求同时进行文件/套接字IO,那么我应该预计会有副作用吗?
CLOSE_ON_EXEC
标志。 - cs95CLOSE_ON_EXEC
似乎是相关的。虽然我也不明白它的作用... - Ben MosherCLOSE_ON_EXEC
指定为1来关闭所有这些打开的文件描述符,以便子进程无法使用它们。 - cs95