3

終了時にクリーンアップアクションを実行する必要があるWindows上のPerlプログラムがあります。を使用してシグナルハンドラーを作成しsigtrapましたが、常に機能するとは限りません。Ctrl-Cをインターセプトすることはできますが、マシンが再起動されたり、プログラムが他の方法で強制終了されたりすると、シグナルハンドラもENDブロックも実行されません。私は、Windowsには実際にはシグナルがなく、Windowsでのシグナル処理はPerlの一種のハックであることを読みました。私の質問は、Windowsの方法で異常終了を処理するにはどうすればよいですか?プログラムが終了する方法や理由に関係なく、クリーンアップコードを実行したい(キャッチできないイベントを除く)。Windowsがシグナルの代わりにイベントを使用することを読みましたが、PerlでWindowsイベントを処理する方法に関する情報が見つかりません。

残念ながら、私にはCPANからモジュールをインストールする権限がないため、バニラActiveStatePerlを使用する必要があります。さらに面白くするために、私が使用しているほとんどのマシンにはPerl5.6.1しかありません。

編集: CPANモジュールまたは新しいバージョンのPerlが必要な場合でも、回答をいただければ幸いです。PerlでのWindowsイベント処理について知りたいのですが、どんな情報でも歓迎します。

4

1 に答える 1

3

すべてのオペレーティング システムで、いつでも任意のプログラムを突然終了できます。kill -9Unix/Linuxのコマンドを考えてみてください。どのプログラムでもそれを行うと、即座に停止します。それをトラップする方法はありません。プログラムがクリーンアップのためにさらに数回のオペレーティング システム サイクルを要求する方法はありません。

Unix と Windows の信号の違いについては詳しくわかりませんが、各 OS が Unix でSIGKILLと呼ばれるものを許可しなければならない理由は想像できるでしょう。

終了要求 (Unix では SIGTERM) をインターセプトするバグのあるプログラムがあり、クリーンアップ フェーズに入る場合を想像してください。クリーンアップする代わりに、プログラムはより多くのメモリを要求するループに陥ります。SIGKILLエマージェンシー コードを引き抜くことができなければ、身動きが取れなくなります。

もちろん、究極のSIGKILLは壁のプラグです。それを引っ張ると、プログラムは(他のすべてと一緒に)金切り声で停止します。あなたのプログラムが「うーん...電源が切れて、マシンの動作が停止した...古いクリーンアップルーチンを開始したほうがいい!」と言う方法はありません。

したがって、すべてのプログラム終了シグナルをトラップする方法はなく、プログラムでそれを考慮する必要があります。あなたができることは、プログラムを実行する前にクリーンアップを行う必要があるかどうかを確認することです。Windows では、プログラムの起動時にレジストリにエントリを配置し、シャットダウンしてクリーンアップを実行するときにエントリを削除できます。Unix では、ディレクトリにピリオドで始まるファイルまたはディレクトリ名を入れることができます$ENV{HOME}

1980 年代にさかのぼると、私は非常に独占的な OS 用の会計ソフトウェアを作成しました。ユーザーが ESCAPE ボタンを押すと、すぐにメイン メニューに戻ると想定していました。ユーザーが注文を入力し、在庫から商品を取り出した場合、トランザクションは不完全になり、注文が不完全であっても、在庫には商品が販売済みとして表示されます。解決策は、誰かが次に注文を入力したときにこれらの不完全な注文を確認し、新しい注文を入力する前に在庫の変更を取り消すことでした。あなたのプログラムは、似たようなことをしなければならないかもしれません。

于 2011-12-05T19:58:24.760 に答える