2017-07-06 60 views
2

我在Python(2.7),使用Popen委託一些工作提高到一個子進程的web服務器:python 2.7 Popen:`close_fds`做什麼?

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 S的一定數量後(大約64) ,過程運行的文件描述符,無法功能 - 它變得完全不響應所有線程似乎永遠阻止,如果他們試圖打開任何文件或插座。

(可能相關:在phantomjs子進程加載一個URL回調到產生它的服務器)

基於this Python bug report,我相信我需要設置close_fds=True所有Popen電話從我的服務器進程中爲了減輕文件描述符的泄漏。但是,我不熟悉周圍exec -ing子過程的機械和繼承的文件描述符這麼多Popen文檔,並在上述錯誤報告的說明的是我不清楚。

這聽起來像它實際上關閉所有打開的文件描述符(其中包括主動要求插槽,日誌文件句柄等)執行子之前,我的過程。這聽起來好像比泄漏套接字好,但仍然會導致錯誤。

然而,在實踐中,當我在Web請求期間使用close_fds=True,它似乎很好地工作,因此到目前爲止,我已經無法構建它實際上是關閉任何其他請求插座,數據庫請求的情況下,等

的文檔狀態:

如果close_fds是真實的,除0,1和2的所有文件描述符將執行子進程之前關閉。

所以我的問題是:是否有「安全」和「正確」通過close_fds=TruePopen在多線程Python的Web服務器?或者,如果其他請求同時執行文件/套接字IO,我是否應該期望這會產生副作用?

+0

我不知道這是怎麼回事。相反,這似乎與POSIX的'CLOSE_ON_EXEC'標誌相似。 –

+0

我不確定這個問題,但是'CLOSE_ON_EXEC'似乎是相關的。我不明白這是爲什麼,但... –

+0

基本上,這個想法是,當你執行一個子進程時,它將覆蓋父進程,擦除除打開的文件描述符之外的所有上下文數據。爲了防止孩子做出對這些文件不需要的任何操作,可以將「CLOSE_ON_EXEC」指定爲1來關閉所有打開的文件描述符,以便孩子不能使用它們。 –

回答

0

我嘗試下面的測試與subprocess32反向移植的Python 3.2/3.3的subprocess的:

import tempfile 
import subprocess32 as subprocess 

fp = open('test.txt', 'w') 

fp.write("some stuff") 

echoed = tempfile.TemporaryFile() 
p = subprocess.Popen(("echo", "this", "stuff"), stdout=echoed, close_fds=True) 
p.wait() 
echoed.seek(0) 

fp.write("whatevs") 
fp.write(echoed.read()) 
fp.close() 

和我的some stuffwhatevsecho this stuff預期的結果test.txt

所以看來的closeclose_fds的意義呢意味着在父進程打開文件(插座等)將執行一個子進程後無法使用。

也值得注意:subprocess32默認close_fds=True在POSIX系統,AFAICT。這意味着它不像聽起來那麼危險。