興味深い問題:アプリケーションの安定性(堅牢性)を高める(パート2)

そこで、トピックhabrahabr.ru/blogs/net/69545から問題の解決策を紹介します -アンマネージリソースの保証されたリリースについて。

同志adontzが正しく指摘したように、問題はCERを使用して解決されます。
CERはConstrained Execution Regionテクノロジーであり、その一部でStackOverflowまたはThreadAbortタイプの非同期割り込みが発生すること、またはジッターが「落ちた」ことを保証することでコードを保護できます。一貫した状態の外部リソース。

トーゴ!


言い換えれば、ランタイムを「強制」してコードセクションをブロックし、実行のためにすべてを準備することができます。スタックとRAMに十分なメモリがあることを確認し、コードをjコード化してから破壊します! -準備されたコードを実行し、次に何かが起こったかどうかを把握します。

プロセスでコードの実行が「落ちる」ことを防ぐために、ランタイムはCER領域で実行できないことに対していくつかの制限を課します。 そして、一般的に、あなたが多くのことをすることができないように:一般に、CERのもとでは、重要な小さなコード(原則として外部リソースを操作する)を「駆動」し、その継続的な実行を保証する必要があります。 必要なものだけです。

だから、重い平日に私たちのラムに戻って、すなわち。 例に移りましょう。 実際にCERを使用するには、ヘルパークラスSystem.Runtime.CompilerServices.RuntimeHelpers向かって掘り下げる必要があります。
私たちにとって最も重要なメソッドはPrepareConstrainedRegionsであり、説明された準備を実行します。たとえば、_future_コールスタックを通過し、プレジットを実行し、ストップマークを配置します(仮想メソッドとインターフェイスを「額」に使用できない理由は明らかです)-動的なディスパッチがあり、実際のコードが実行されるまで呼び出しスタックを作成することは不可能です。 今から楽しい部分です。 このメソッドの使用は次のようになります。
 ... System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions(); try {} finally {    // atomic-    } ... 
そうです-空のtryブロック、およびすべての中断されない操作はfinallyブロックに入れなければなりません!

チェックするには-このテスト:
 Thread t = new Thread(new ThreadStart(        () => {        RuntimeHelpers.PrepareConstrainedRegions();        try { }        finally {            while (true) { }    }}));    t.Start();    Thread.Sleep(1000);    t.Abort();    t.Join(); 

プログラムは機能し、終了しません。 try-finallyをコメントアウトすると、プログラムは終了します。 絶対-ThreadAbortException _not_のリクエストは、finallyブロックの終わりまで延期され(無限のwhile(true){}ループのために発生しません)、すぐに(ほぼすぐに)動作します

これで、IntPtrの例からコードを「修正」する方法がわかりました。
 IntPtr ptr = IntPtr.Zero; try {    //...    System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions();    try { }    finally {        ptr = Marshal.AllocHGlobal(500);    }     // .., .. } finally {    if( ptr != IntPtr.Zero ) Marshal.FreeHGlobal(ptr); } ... 

将来のために-MSDNは、管理されていないリソースを避けることを推奨しています。 CLRを作成する目的の1つは、継承されたアンマネージコードとリソースと対話することであるという事実を踏まえると、やや奇妙なアドバイスです。

そのため、管理されていないリソースのある作業場所を慎重に確認することをお勧めします。これらの時点で完全に機能するプログラムでも、2〜3個の重大なバグを見つけることができることがわかります。

メモリリークの対処に役立つものだけを整理したことは明らかです。 しかし、CER自体については触れませんでした。CERに適したメソッドの契約、CER内で呼び出すためのイベントの準備、仮想メソッドの準備、クリティカルファイナライザー、FailFastおよびMemoryBarriersを使用して、プログラムの信頼できる操作を保証し、管理されていないリソースリークを防ぎます。 それについて書くか、MSDNに送信する必要がありますか?

Source: https://habr.com/ru/post/J69650/


All Articles