我想在PHP中使用命名管道來完成一些IPC。我有一個名爲管道通過如何使用命名管道設置fopen超時
$pipePath = __DIR__ . '/pipe';
posix_mkfifo($pipePath, 0600);
創建有整理一番計算後應寫入該管道另一個進程。我可以等待其完成的東西,如讀取結果:
$result = file_get_contents($pipePath);
或更詳細的
$in = fopen($pipePath, 'r');
$result = fread($in, 8192);
fclose($in);
(我已經簡化了第二種方法,在實際的代碼我會檢查是否存在錯誤,在一個循環的情況下運行fread
結果> 8192個字節等)
然而,當其他工藝應該結束,我不相信它是成功的,所以我想有一個超時試圖閱讀 結果。等待一段時間後,我想放棄並報告一個錯誤,說它崩潰了,等等。使用這兩種方法,PHP代碼將永久掛起(或長時間等待),以等待某些內容寫入管。具體而言,file_get_contents
和fread
將掛起。
唯一的解決辦法我能想出是這樣的:
$timeout = 10; //seconds
for ($i = 0; $i < $timeout; $i++) {
$in = @fopen($pipePath, 'rn');
if ($in) break;
sleep(1);
}
if (!$in) {
throw new RuntimeException("The other process did not finish in the allotted time");
}
$result = fread($in, 8192);
fclose($in);
它使用無證'n'
標誌fopen
如在this question的意見之一。它會導致fopen
呼叫在阻塞時立即失敗。
不過,我不喜歡這個解決方案有兩個原因:
- 它通過檢查管每一秒做不必要的工作。
- 如果其他進程中的計算需要1.01秒才能完成,這將等待整整2秒鐘以獲得結果。對於我想要做的一些事情來說,這已經足夠浪費時間了,值得嘗試解決這個問題。
當在一個URL上調用fopen
時,我可以添加一個context參數指定一個超時值。但是,這似乎不適用於此,也不設置默認套接字超時。
有沒有更好的方法來做到這一點與管道?如果沒有,我可能會考慮切換到Unix套接字,但這些在其他進程中不太容易支持,所以我寧願不這樣做。
(僅供參考,我只關心Linux的;沒有必要有一些在Windows上運行還是別的,萬一這個問題)
不知道爲什麼我沒有想到使用select。我認爲問題的部分原因是我的問題最初聲稱「fopen」會掛起,但實際上它是懸掛的「fread」。 – Austin