2016-09-06 63 views
1

我有以下程序,旋轉起來100個不同的工藝(是的,我知道我應該關閉的端口,我只是不這樣做在這個例子中)後:Subproccesses仍然活着,球拍程序暫停

#lang racket ; evil.rkt 

(require compiler/find-exe) 

(for ([i (in-range 100)]) 
    (process* (find-exe) "-e" "(let loop() (loop))")) 

正如預期的那樣,當我運行這個程序,並運行ps -fe | grep 'racket'讓所有正在運行的球拍進程的列表,我看到的是這樣的:

.... 
73187 ??   0:00.47 /Users/leif/racket/racket/bin/racket -e (let loop() (loop)) 
73188 ??   0:00.44 /Users/leif/racket/racket/bin/racket -e (let loop() (loop)) 
73189 ??   0:00.45 /Users/leif/racket/racket/bin/racket -e (let loop() (loop)) 
73190 ??   0:00.45 /Users/leif/racket/racket/bin/racket -e (let loop() (loop)) 
73191 ??   0:00.43 /Users/leif/racket/racket/bin/racket -e (let loop() (loop)) 
73192 ??   0:00.41 /Users/leif/racket/racket/bin/racket -e (let loop() (loop)) 
73193 ??   0:00.39 /Users/leif/racket/racket/bin/racket -e (let loop() (loop)) 
73194 ??   0:00.35 /Users/leif/racket/racket/bin/racket -e (let loop() (loop)) 
73195 ??   0:00.34 /Users/leif/racket/racket/bin/racket -e (let loop() (loop)) 
73196 ??   0:00.34 /Users/leif/racket/racket/bin/racket -e (let loop() (loop)) 
73197 ??   0:00.29 /Users/leif/racket/racket/bin/racket -e (let loop() (loop)) 
.... 

的問題是,該計劃甚至之後終止,這些進程仍在運行。

如果我在shell中運行它,並按Ctr + C終止程序,大多數進程停止。但是,偶爾有一兩個人會繼續跑步。

當我切換到使用process而不是process*此問題消失。有什麼我可以做的,以確保我的子流程停止時,我終止程序?

回答

4

這裏的問題是,默認情況下,由Racket產生的子進程在程序終止時不會由託管人關閉。

你沒有這個問題,process的原因是因爲process功能啓動一個shell(如/bin/sh),並在運行您的命令。該shell正在照顧子流程。另一方面,process*直接運行你的子進程,因此Racket負責它,否則它將成爲殭屍進程。

當你在一個shell(而不是DrRacket)中運行這個問題時,這個問題的原因要少得多,因爲你的shell可能在你自己的進程組中擁有你的進程及其所有子進程。因此,當按下Ctr + C時,shell會向進程組中的所有進程發送SIGINT,其中包括進程的所有子進程。有時候,不幸的是,有些流程太新,無法添加到組中(或者是在SIGINT發送後創建的時刻,我不完全確定這裏的機制),因此它們仍然活着。

所有這一切都可以通過周圍設置current-subprocess-custodian-mode參數'kill(或'interrupt),以便在終止前球拍custodian將終止您的過程中的工作。從而改變你的代碼看起來像:

#lang racket 

(require compiler/find-exe) 

(parameterize ([current-subprocess-custodian-mode 'kill]) 
    (for ([i (in-range 100)]) 
    (process* (find-exe) "-e" "(let loop() (loop))"))) 

(請注意,這仍然依靠球拍關閉你的子過程如果使用圖書館像ffi/unsafe並導致球拍段錯誤,子進程仍將運行。 )

作爲附錄,請注意,只有當程序結束時(或者當前託管人關閉某些東西,比如在沙箱中),如果您希望在子進程停止之前停止子進程自己發送一箇中斷/終止信號,您可以使用process*函數返回的回調函數執行該操作。