2013-03-12 79 views
4

的Python 2.7.3在Solaris 10上防止子線程死亡時線程subprocess.popen終止我的主腳本?

問題

  1. 當我的子進程有一個內部分割故障(核心)發行或用戶通過一個外部SIGTERM或SIGKILL,殺死它從我的殼主程序的信號處理程序處理一個SIGTERM(-15),我的父程序退出。 這是真的嗎?或者它是一個糟糕的python構建?

背景和代碼

我有一個Python腳本,首先生成一個工人管理線程。工作管理線程然後產生一個或多個工作線程。我的主線程中還有其他內容,我無法阻止。我的管理線程的東西和工作線程是堅如磐石的。好幾年我的服務,而無需重新啓動,但然後我們有這個subprocess.Popen場景:

在工作線程的run方法,我使用:

class workerThread(threading.Thread): 
    def __init__(self) : 
     super(workerThread, self).__init__() 
    ... 
    def run(self) 
     ... 
     atempfile = tempfile.NamedTempFile(delete=False) 

     myprocess = subprocess.Popen(['third-party-cmd', 'with', 'arguments'], shell=False, stdin=subprocess.PIPE, stdout=atempfile, stderr=subprocess.STDOUT,close_fds=True) 
     ... 

我需要使用myprocess.poll()檢查過程終止,因爲我需要掃描atempfile,直到找到相關信息(文件可能> 1 GiB),並且由於用戶請求或流程運行時間過長,我需要終止進程。一旦找到我正在查找的內容,我將停止檢查stdout臨時文件。在外部進程終止之後以及工作線程終止之前,我將對其進行清理。我需要stdin PIPE,以防我需要在孩子的標準輸入流中注入一些交互響應。

在我的主程序中,如果我的主python程序以SIGTERM或SIGINT(Ctrl-C)結尾(如果從shell運行),我將爲SIGIN和SIGTERM處理程序執行清理。

有沒有人有線程中的子信號處理固體2.x配方? ctypes sigprocmask等

任何幫助將不勝感激。我只是在尋找一個'官方'配方或BEST hack,如果有的話。

注意

我使用Python的限制版本。我必須使用2.7.3。第三方-cmd是我沒有源代碼的程序 - 修改它是不可能的。

+0

歡迎來到SO。儘管我沒有給你答案,但我建議你刪除大部分「文字牆」。這可能會嚇跑潛在的回答者。至少,將它分成幾部分。 – xxmbabanexx 2013-03-12 01:34:00

+0

感謝您的回覆。不知道如何編輯它,並得到我想要傳達的信息。 – whistler 2013-03-12 01:43:39

+0

我編輯了您的問題,以幫助使其更具可讀性。你不需要改變你寫的內容,但是將它分成小節是有幫助的。 – xxmbabanexx 2013-03-12 01:47:35

回答

1

在描述中有很多東西看起來很奇怪。首先,你有幾個不同的線程和過程。誰在崩潰,誰在接受SIGTERM,誰在接收SIGKILL,以及由於哪些操作?

第二:你父母爲什麼會收到SIGTERM?它不能被隱式發送。有人正在直接或間接調用kill給父進程(例如,通過殺死整個父進程組)。

第三點:當您處理SIGTERM時,程序如何終止?根據定義,如果程序沒有處理,程序就會終止。如果處理完畢,則不會終止。真正發生的事情是什麼?

建議:

$ cat crsh.c 
    #include <stdio.h> 

    int main(void) 
    { 
     int *f = 0x0; 

     puts("Crashing"); 
     *f = 0; 
     puts("Crashed"); 
     return 0; 
    } 
    $ cat a.py 

    import subprocess, sys 

    print('begin') 
    p = subprocess.Popen('./crsh') 
    a = raw_input() 
    print(a) 
    p.wait() 
    print('end') 
    $ python a.py 
    begin 
    Crashing 
    abcd 
    abcd 
    end 

這工作。沒有信號傳遞給父母。你是否在程序中找到了問題?

如果問題是發送給多個進程的信號:您可以使用setpgid爲孩子設置一個單獨的進程組嗎?

是否有任何理由創建臨時文件?它是臨時目錄中創建的1 GB文件。爲什麼不用管道標準輸出?如果你確實需要處理你的父程序中的信號(爲什麼你沒有嘗試/除了KeyboardInterrupt,例如?):可能signal()與多線程程序的未指定行爲導致這些問題(例如,調度一個信號給一個不處理信號的線程)?

NOTES 
    The effects of signal() in a multithreaded process are unspecified. 

無論如何,嘗試用更精確什麼是你的程序的線程和進程來解釋,他們做什麼,如何進行信號處理程序設置和爲什麼,是誰發出的信號,誰接收,等等,等等等等等等。

+0

是的。你的例子確實有用,但是我的問題要複雜得多。謝謝你指出它很混亂。我更多地澄清了這些文字。我的popen發生在一個線程中,實際上是一個線程中的線程,如上所述。使用setpgid不起作用,因爲我已經嘗試使用preexec_fn,結果是一樣的。管道標準輸出可能導致標準輸出管道中數據大小超過64k塊時發生死鎖。使用等待/與管道通信肯定會導致1GB數據的進程出現死鎖。使用信號進行線程處理肯定會導致我的問題。 – whistler 2013-03-12 04:08:20

+1

在問題出現的地方創建一個最簡單的示例。 – hdante 2013-03-12 18:32:30

+0

@whilster:[這個例子顯示數據大於64K時沒有死鎖](https://gist.github.com/zed/3b4606d811fcf6530795) – jfs 2013-03-13 17:31:19