2013-03-22 67 views
1

在Windows 8,Python 3.3下運行,我產生了3個應該依次運行的進程:首先簽署一個可執行文件,其次,使用Inno Setup構建一個工具包(它涉及第一步中的可執行文件),最後使用第二步中的輸出對其進行簽名。然而,從時間開始,我得到了似乎是一種競爭條件,簽名工具在其中抱怨它無法簽署可執行文件。在我看來,第二個進程不會以某種方式(或操作系統)釋放文件句柄...查找錯誤代碼後,儘管它應該完成(我使用process.communicate()來確保) 。我也懷疑是因爲使用time.sleep()似乎解決了這個問題。子進程似乎結束,但不釋放文件句柄

是否有可能第二個進程以某種方式分離自己並在後臺運行?但是如果是這樣的話,我仍然能夠始終在日誌文件中看到正確登錄的操作(例如第一次輸出,構建,第二次簽名(不管它是成功還是不成功))?不應該從溝通中獲得輸出這一事實意味着所有資源(包括文件句柄)都已發佈?代碼如下:

def do_build(): 
''' 
Prepare the kit. 
''' 
    global kit_file 
    kit_file = ''.join([OUTPUT_FILENAME, '_', version]) # do not add '.exe', as Inno does it during build 
    DESCR = 'Execute Build' 
    logf.write(BEGIN + DESCR + SEP2) 

    def run_command(c, ex): 
     with subprocess.Popen(c, stdout = subprocess.PIPE, stderr = subprocess.PIPE, executable = ex) as proc: 
      stdout_data, stderr_data = proc.communicate() 
      logf.write(str(stdout_data, 'cp1252')) 
     if proc.returncode != 0: # log errors if needed 
      logf.write(str(stderr_data, 'cp1252')) 
      sys.exit()  

    sign_exe = [SIGNCODE, '-cn', TTT, '-n', KIT_TYPE2.upper(), '-i', URL, '-t', TSURL] 
    sign_kit = sign_exe[:] # make copy 
    sign_exe.append(os.sep.join([PDIR, DEPLOYMENT, EXECUTABLE])) # sign the executable 
    run_command(sign_exe, os.sep.join([PDIR, SIGNCODE])) 

    compile = [ISCC, ''.join(['/O', OUTPUT_DIR]), ''.join(['/F', kit_file]), os.sep.join([PDIR, ISS_FILE])] # compile using the ISS script 
    run_command(compile, os.sep.join([ISSC_PATH, ISCC])) 

    # time.sleep(something) here seems to save the day... 

    sign_kit.append(os.sep.join([PDIR, ''.join([kit_file, '.exe'])])) # sign the kit, don't forget '.exe' 
    run_command(sign_kit, os.sep.join([PDIR, SIGNCODE])) 
    logf.write(END + DESCR + SEP2) 

我正在使用InnoSetup 5,命令行工具iscc.exe,FWIW。

對此行爲的任何解釋?我看到的唯一解決方法是在嘗試上次簽名之前使用os.access(文件,os.W_OK)。

我沒有運行殺毒軟件,也無法想象會干擾簽名過程的其他任何事情。

+1

使用'with'語句在進程上做了一個'wait',但是它的['Handle'](http://hg.python.org/cpython/file/bd8afb90ebf2/Lib/subprocess.py#l427)( Lib/subprocess.py)只能通過GC通過'__del__'關閉。也許這是時機問題。在'with'之後,在'run_command'的末尾嘗試一個手動'proc._handle.Close()'。 – eryksun 2013-03-24 00:13:18

+0

謝謝你,Eryksun。我一定會檢查你的第一個建議;這是有道理的(在這種情況下,我發現Pyhton也有一個垃圾收集器......)。這將需要一些廣泛的測試,但我會回來並相應報告。 – 2013-03-25 15:52:13

+0

雖然我不確定其他問題,你會如此善意地重述它嗎?我不想假設,也許我錯過了一些東西。感謝您的時間。 – 2013-03-25 16:01:01

回答

0

原來我一直在找錯方向的罪魁禍首。

經過更多的研究 - 並未能找出哪個進程鎖定了我的文件(使用Process Explorer,直接從我的腳本LockHunter處理工具) - 我發現了足夠的證據證明Windows Defender是「罪犯」。顯然,它在Windows 8中很好地集成在一起,您可以完全忘記它的實時保護模塊正在後臺運行。有時候,一旦我的文件可執行文件被創建,它就會將其鎖定無限的時間,這足以讓我隨後嘗試對它進行簽名......失敗。

對於我最初的錯誤推定,我表示歉意。

相關問題