shell命令管道未讀完阻塞了子進程,與等待其結束的父進程死"鎖"。


在exec執行一個子進程,我們希望使用管道取得子進程在重定向后的標准輸出上的結果,同時等待子進程的結束。那么是等待子進程結束后才取管道數據,還是邊取數據邊等待子進程結束呢?

這里有一個調試的例子。u0_a89是例子中app的用戶id。

android app 進程 5990,exec了一個sh子進程 6251,去執行命令子進程。

   

可以查看到app進程由zygote創建,app進程創建了6251,6251創建了6252,並且app進程及其子進程都阻塞去睡眠了。原本6252子進程執行着一個不要阻塞並且十分短小的任務,一瞬就應該完成並結束的。但卻無端阻塞走去睡眠了。而sh子進程6251又在等待進程2652結束,app進程也在等待sh子進程結束,這就僵直了。

 

原因是app沒有分配足夠空間去取出管道中的數據,使得 read( pipe, buf, space /** 0 */) 返回 0,再加上epoll為ET觸發,然后就沒有去讀管道了。管道堵滿了數據,子進程不能完成數據的傳輸也被阻塞了。

一般來說,如果子進程執行的任務只有少量結果輸出,不會塞滿管道,即使你來不及去讀出管道的數據,子進程也已經將結果都填進管道了,也就關閉管道寫端,順利結束。這種情況下,不論你是先讀管道,抑或先等待子進程結束也者沒有問題。但是當子進程任務輸出大量結果數據時,情況就不一樣了,你必須及時去讀管道,讓子進程可以去寫管道。如果讀的操作不注意,就會出現上面的錯誤,即使同時也在reactor上等待進程的結束事件,卻永遠都等不到那一刻了,因為互相死鎖了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM