2011-12-05 94 views
3

我在Windows上有一個需要在退出時執行清理操作的Perl程序。我用sigtrap編寫了一個信號處理程序,但它並不總是有效。我可以攔截Ctrl-C,但是如果機器重新啓動或程序以其他方式死亡,那麼信號處理程序和END塊都不會運行。我已經讀過Windows沒有真正的信號,並且Windows上的信號處理在Perl中是一種破解。我的問題是,我怎樣才能處理異常終止Windows的方式?我想運行我的清理代碼,不管程序終止的方式或原因(不包括無法捕獲的事件)。我讀過Windows使用事件而不是信號,但是我找不到有關如何在Perl中處理Windows事件的信息。如何在Windows上處理Perl中的異常程序終止

不幸的是,我沒有權限從CPAN安裝模塊,所以我必須使用vanilla ActiveState Perl。爲了讓事情更有趣,我使用的大多數機器都只有Perl 5.6.1。

編輯:我將不勝感激任何答案,即使他們需要CPAN模塊或更新版本的Perl。我想了解Perl中的Windows事件處理,並且歡迎任何信息。

+1

Perl 5.6.1 ..這是什麼,像10歲?你在這些機器上獲得了Win98/2000/ME? =) – TLP

+0

我們在所有臺式機上使用Windows XP。當微軟停止支持XP時,我們希望能夠在Windows 7上運行。不管信不信,我們的一些機器仍然使用IE6,因爲我們的一些內部應用程序不會運行其他任何程序。 – Jonathan

+2

我的意思是說,perl 5.6.1和這些操作系統一樣陳舊。它總是讓我想知道爲什麼人們不更新perl。這不像是不更新任何其他軟件的好主意。 – TLP

回答

3

在所有操作系統中,您總是可以突然終止任何程序。想一想在Unix/Linux中的kill -9命令。你在任何程序上都這樣做,並立即停止。沒辦法去捕捉它。沒有辦法讓程序要求更多的操作系統週期進行清理。我不知道爲什麼每個操作系統都必須允許我們在Unix中調用SIGKILL - 一種可靠而直接的殺死任何程序的方法。

想象一下,您有一個截獲終止請求(Unix中的SIGTERM)的錯誤程序,並且它進入了一個清理階段。而不是清理,程序反而陷入了一個需要越來越多內存的循環中。如果你不能拉動緊急電線,你會被卡住。

終極SIGKILL,當然是插在牆上。把它拉出來,程序(連同其他所有的東西)就會停下來。沒有辦法你的程序可以說「嗯......電源關閉,機器已停止運行......更好地啓動舊的清理程序!

因此,你無法捕捉每個程序終止信號,並且,您的程序必須對此進行解釋。你可以做的是看你的程序是否需要在運行之前進行清理。在Windows上,您可以在程序啓動時在註冊表中放入一個條目,並在關閉並清理時將其刪除。在Unix中,您可以在$ENV{HOME}目錄中輸入一個文件或目錄名稱作爲句點。

早在20世紀80年代,我爲非常專有的操作系​​統編寫了會計軟件。當用戶按下ESCAPE按鈕時,我們假設立即返回到主菜單。如果用戶正在輸入訂單並從庫存中取出貨物,交易將不完整,並且庫存將顯示已售出,即使訂單不完整。解決方案是在下次有人輸入訂單時檢查這些不完整的訂單,並在輸入新訂單之前退出庫存中的更改。你的程序可能需要做類似的事情。

+0

我明白,但那不是我所問的。在我原來的問題中,我說過「排除不能被發現的事件」。我知道我無法趕上相當於SIGKILL的Windows或其他即時致命的錯誤,但我希望能夠捕捉到相當於SIGTERM和類似的東西。但由於某種原因,我的信號處理程序沒有被調用,除非在Ctrl-C上。我想了解如何直接使用Windows事件,而不是經歷Unix信號的不完整模擬。 – Jonathan

+1

@Jonathan - 對不起,我很困惑。 Perl在Cntrl-C上模擬SIGTERM,但在其他情況下,Windows不使用可捕獲的信號。您可以查看與Windows事件處理綁定的[Win32 :: Events](http://search.cpan.org/~cjm/Win32-IPC/lib/Win32/Event.pm)。這就是Windows所使用的而不是信號。 –

+0

對Win32 :: Events的引用很有幫助,但文檔只解釋瞭如何創建和操作事件。我需要捕捉當進程死亡時產生的任何事件。你能指出我的任何信息嗎?我用google搜索了「perl中的窗口事件」,幾乎沒有任何東西。 – Jonathan

相關問題