2015-11-02 15 views
1

確保子進程在父進程終止時終止非常棘手。我發現一個強大的解決方案from Python in Linux是指示內核在父代終止時使用prctl(PR_SET_PDEATHSIG, SIGTERM)來終止子進程。考慮到prctl()來自C標準庫,這大概可能來自C或C++。Java:如何在子進程中調用prctl()

關於如何殺死Java中的子進程有幾個問題,請參閱[1]。 但是,我發現的東西和使用prctl()的方法一樣強大。如果父母收到SIGKILL,或者他們需要修改子代碼,則大多數解決方案都會失敗。通過讓操作系統爲我們完成這項工作,無論父母發生什麼事情,孩子總是會被成功殺死,並且子代碼不需要修改。

如何在由Java ProcessBuilder產生的子進程中調用prctl(PR_SET_PDEATHSIG, SIGTERM)

回答

3

您可以用位C的去做,只要你不擔心幾個條件,並瞭解它有侷限性。

prctl(PR_SET_PDEATHSIG, …)系統調用是Linux內核的一部分,並有一對夫婦的規則 - 它不下去fork(),它不下去exec()成的setuid/setgid的二進制文件。

限制是:

  • 這是一個簡單的程序,它會如果從子進程啓動別的東西,除非你把一些限制可怕的殺人的事情。
  • 它不會跨越可執行模型(如32-> 64位),這是比較少見的工作
  • 它不會與靜態鏈接的二進制文件(罕見)

考慮到這些侷限性的工作,我們可以從一些調用此係統調用的C中創建一個小型預加載庫。因此,舉例來說:

#include <sys/prctl.h> 
#include <sys/types.h> 
#include <signal.h> 

__attribute__((constructor)) 
static void on_load() { 
    prctl(PR_SET_PDEATHSIG, SIGTERM); 
} 

使用gcc -fPIC -shared -o term_death.so term_death.c

編譯當您使用的完整路徑此二進制LD_PRELOAD環境變量,正在啓動的任何程序都將被髮送SIGTERM時,他們的父進程被殺死。

這是從C面設置 - 我們現在有一個輔助庫,讓你要求的行爲。

得到這個從Java方面的工作。

我們需要注入的完整路徑。所以到了的ProcessBuilder的LD_PRELOAD環境變量,所以像:

ProcessBuilder pb = new ProcessBuilder(); 
Map<String, String> env = pb.environment(); 
env.put("LD_PRELOAD", "/home/me/development/experiments/term_death.so"); 
再次

,你需要指定路徑.so,使其可以加載。

當你pb.start()它會繼承LD_PRELOAD環境變量。在加載可執行文件時,它運行on_load代碼(因爲它被標記爲構造函數),並說當父進程終止時進程將收到SIGTERM

這有點難看,但應該解決這個問題。

相關問題