2016-12-02 14 views
2

私は他人のサービスを使用するプログラムを持っています。プログラムがクラッシュした場合、それらのサービスを閉じる最善の方法は何ですか?サーバー側では、クライアントが定期的に無効であるかどうかを監視するチェッカーを定義します。しかし、私たちはクライアントで何かできますか?この場合、通常のRAIIがまだ動作しているかどうかはわかりません。私のコードはCとC++で書かれています。プログラムがクラッシュした場合のリソースの解放方法

+0

申し訳ありません。私のコードはcとC++を使います。私は自分の質問を修正した。 –

+0

クラッシュはクラッシュです。プロセスがなくなり、あなたができることは何もありません。サービス接続は、基本プロトコル(TCP)によって閉じられる必要があります。 – Kimi

+1

プログラムがクラッシュすると、オペレーティングシステムは通常、クラッシュしたプログラムのリソースを解放します。 – Bamaco

答えて

6

アプリケーションでハードクラッシュが発生した場合は、RAIIパラダイムの一部であるか、mainの最後に呼び出すメソッドであっても、慎重に作成されたクリーンアップコードは実行されません。 アプリケーションのクリーンアップコードのいずれも、アプリケーションを終了させるクラッシュの後で実行されません。

もちろん、これは例外ではありません。それらは最終的にアプリケーションを終了させるかもしれないが、制御された方法でこの終了を引き起こす。一般に、ランタイムライブラリは未処理の例外とトリガ終了をキャッチします。途中でRAIIベースのクリーンアップコードが実行されますが、例外もスローされます。それから、あなたは思いのほかメモリから切り裂かれてしまいます。

しかし、たとえあなたアプリケーションのクリーンアップコードを実行できない場合は、まだあなたの後にクリーンアップしようとしますオペレーティングシステム。これにより、解放されていないメモリ、ハンドル、およびその他のシステムオブジェクトの問題が解決されます。一般に、クラッシュした場合、これらのものをリリースする心配はありません。アプリケーションの状態が矛盾しているので、クリーンアップコードを実行しようとすると、予測できない、誤った動作につながるだけでなく、膨大な時間を浪費します。ちょうどクラッシュし、システムがあなたの混乱に対処するようにしてください。 As Raymond Chen puts it

建物が破棄されています。床を掃除してゴミ箱を空にしてホワイトボードを消しても構いません。また、建物の出口に並んでいないようにして、誰もが出入り口に出入りできるようにしてください。あなたがしているのは、解体チームがこれらの無駄な家事労働を終えるのを待つことだけです。

あなたがする必要があります。他のすべてをスキップします。

このアプローチの唯一の問題は、オペレーティングシステムによって制御されていないリソース(別のシステム上のリモートリソースなど)を管理しているときに、この質問に示すように唯一の問題です。その場合は、あなたができることはほとんどありません。 最高のシナリオは、クラッシュしないようにアプリケーションをできるだけ堅牢にすることですが、それでも完璧な解決策ではありません。電源が失われたときに何が起こるかを考えてみてください。ユーザの猫が壁からコードを引っ張ったためです。おそらくクリーンアップコードが実行される可能性があります。したがって、アプリケーションがクラッシュしない場合でも、制御の外にある終了イベントが存在する可能性があります。したがって、外部リソースは、エラーが発生した場合でも堅牢である必要があります。タイムアウトは標準的な方法であり、ポーリングよりもはるかに優れた解決方法です。

特定のユースケースによっては、初期化で一貫性チェックとクリーンアップコードを実行することもできます。これは、継続的に実行され、終了後直ちに再開される予定のサービスに対して行うものである可能性があります。次に再起動すると、データや外部リソースの一貫性をチェックし、必要に応じてそれらを解放したり、再初期化したり、通常どおり続行します。ユーザーが適時に再起動するという保証はないため、明らかにこれは典型的なアプリケーションのための悪い解決策です。

-1

atexitを調べると、プログラムの終了時にリソースを解放する必要があるかもしれません。私はそれが間違いないとは思わない。

しかし、実際には、プログラムがクラッシュしないようにすることに集中する必要があります。 「回復不能」なエラーが発生した場合でも、エラー処理コードに投資する必要があります。 Seg-Faultや他の同様のOS関連のエラーによってエラーが発生した場合は、SEH例外を有効にするか(これがWindows固有かどうかはわかりません)、通常のtry-catchブロックでSEH例外を捕まえることができますこれらのエラーを傍受して処理するシグナルハンドラを記述してください。

+1

atexitは本当に解決策ではありません。質問がここで尋ねられるのではなく、クラッシュの場合ではなく、アプリケーションが終了するときにのみ呼び出されるからです。私はそれがグローバルな未処理の例外ハンドラによって呼び出されるとは思っていません(私は確かではありませんが)。はい、SEHはWindows固有であり、アプリケーションによって処理できない、または処理されるべきではない特定のSEH例外があります。これにより、完全に解決することのできない醜い低レベルの問題が発生することがありますので、試してみることをお勧めします。例外ハンドラは、プロセスの状態について仮定することはできません。 –

3

他の回答が明らかになると、制御されていないクラッシュ(つまり、C++例外の巻き戻しメカニズムを引き起こさない障害)後のクリーンアップを望んでいるのはおそらくどこにも至りません。いくつかのケースをカバーしても、失敗するケースがあり、そのケースに深刻な脆弱性があります。

あなたは、クラッシュの原因は、あなたが「他の人からのサービス」であるということです。私はこれを、あなたが潜在的なクラッシュの原因である、信頼できないコードをインプロセスで実行していることを意味します。この場合、信頼できないコードを「プロセス外」で実行し、パイプや共有メモリなどを介してメインプロセスに通信することを検討することもできます。次に、この子プロセスのクラッシュを分離し、メインプロセスで制御されたクリーンアップを実行できます。別のプロセスは実際にあなたが行うことができる最も軽量なもので、呼び出しコードの破損を避けるために必要な強力な分離を提供します。

コールごとにプロセスをフォークするのはパフォーマンスが重視される場合、複数のコールに対して子プロセスを有効に保つことができます。

1

通常の操作と監視の2つのモードをプログラムに持たせる方法があります。

通常の方法で起動すると、それだろう:バックグラウンドモニタとして

  1. 法。
  2. 自身のサブプロセスを起動し、内部引数(通常の引数があればそれと衝突しないもの)を渡します。
  3. サブプロセスが存在すると、サーバーに保持されているすべてのリソースが解放されます。

内部引数で起動すると、それはなります

  1. は、ユーザーインターフェイスを公開し、サーバーのリソースを使用して、「正常に動作します」。
関連する問題