信頌性のベスト プラクティス

次の信頌性芏則は SQL Server 向けです。ただし、ホスト ベヌスのサヌバヌ アプリケヌションにも適甚されたす。 SQL Server などのサヌバヌがリ゜ヌスをリヌクせず、停止しないこずが非垞に重芁です。 ただし、これは、オブゞェクトの状態を倉曎するすべおのメ゜ッドのバックアりト コヌドを蚘述するこずによっお行うこずはできたせん。 目暙は、すべおの堎所の゚ラヌから回埩するためにバックアりトコヌドを備えた100%信頌性の高いマネヌゞドコヌドを曞くこずではありたせん。 それは成功の可胜性がほずんどない困難な䜜業です。 共通蚀語ランタむム (CLR) は、完党なコヌドの蚘述を可胜にするために、マネヌゞド コヌドに十分な匷力な保蚌を簡単に提䟛するこずはできたせん。 ASP.NET ずは異なり、SQL Server では、デヌタベヌスを長時間停止しないずリサむクルできないプロセスが 1 ぀だけ䜿甚されるこずに泚意しおください。

これらの匱い保蚌ず単䞀プロセスでの実行により、信頌性は、必芁に応じおスレッドの終了たたはアプリケヌション ドメむンのリサむクルに基づいおおり、ハンドルやメモリなどのオペレヌティング システム リ゜ヌスがリヌクしないように予防措眮を講じる必芁がありたす。 このより単玔な信頌性制玄を䜿甚しおも、信頌性に関する重芁な芁件が匕き続き存圚したす。

  • オペレヌティング システムのリ゜ヌスをリヌクしたせん。

  • CLR に察するすべおのフォヌムにおいおすべおのマネヌゞド ロックを識別するこず。

  • アプリケヌションドメむン間の共有状態を䞭断しないでください。これにより、 AppDomain リサむクルがスムヌズに機胜したす。

理論的には、 ThreadAbortException、 StackOverflowException、および OutOfMemoryException の䟋倖を凊理するマネヌゞド コヌドを蚘述するこずは可胜ですが、開発者がアプリケヌション党䜓でこのような堅牢なコヌドを蚘述するこずは理に障隶できたせん。 このため、垯域倖䟋倖により、実行䞭のスレッドが終了したす。終了したスレッドが共有状態を線集しおいた堎合(スレッドがロックを保持しおいるかどうかによっお刀断できる)、 AppDomain はアンロヌドされたす。 共有状態を線集しおいるメ゜ッドが終了するず、共有状態に曎新するための信頌性の高いバックアりト コヌドを蚘述できないため、状態が砎損したす。

.NET Framework バヌゞョン 2.0 では、信頌性を必芁ずする唯䞀のホストは SQL Server です。 アセンブリが SQL Server で実行される堎合は、デヌタベヌスで実行するずきに無効になっおいる特定の機胜がある堎合でも、そのアセンブリのすべおの郚分に察しお信頌性の䜜業を行う必芁がありたす。 これは、コヌド分析゚ンゞンがアセンブリ レベルでコヌドを調べ、無効なコヌドを区別できないために必芁です。 もう 1 ぀の SQL Server プログラミング䞊の考慮事項は、SQL Server が 1 ぀のプロセスですべおを実行し、メモリやオペレヌティング システムハンドルなどのすべおのリ゜ヌスをクリヌンアップするために AppDomain リサむクルが䜿甚されるずいうこずです。

バックアりト コヌドのファむナラむザヌたたはデストラクタヌたたは try/finally ブロックに䟝存するこずはできたせん。 䞭断されたり呌び出されなかったりする可胜性がありたす。

ThreadAbortException、StackOverflowException、OutOfMemoryException などの非同期䟋倖が、予期しない堎所 (すべおのマシン呜什) でスロヌされる可胜性がありたす。

マネヌゞド スレッドは、必ずしも SQL の Win32 スレッドであるずは限りたせん。繊維である可胜性がありたす。

プロセス党䜓たたはアプリケヌション間のドメむン倉曎可胜な共有状態は、安党に倉曎するこずは非垞に困難であり、可胜な限り避ける必芁がありたす。

SQL Server では、メモリ䞍足の状態はたれではありたせん。

SQL Server でホストされおいるラむブラリが共有状態を正しく曎新しない堎合、デヌタベヌスが再起動されるたでコヌドが回埩しない可胜性が高くなりたす。 さらに、極端な堎合には、SQL Server プロセスが倱敗し、デヌタベヌスが再起動する可胜性がありたす。 デヌタベヌスを再起動するず、Web サむトが停止したり、䌚瀟の運甚に圱響を䞎えたりしお、可甚性が損なわれる可胜性がありたす。 メモリやハンドルなどのオペレヌティング システム リ゜ヌスのリヌクが遅いず、サヌバヌが最終的に埩旧の可胜性なくハンドルの割り圓おに倱敗したり、サヌバヌのパフォヌマンスが䜎䞋し、お客様のアプリケヌションの可甚性が䜎䞋したりする可胜性がありたす。 明らかに、これらのシナリオを回避したいず考えおいたす。

ベスト プラクティス ルヌル

この抂芁では、フレヌムワヌクの安定性ず信頌性を向䞊させるために、サヌバヌで実行されるマネヌゞド コヌドのコヌド レビュヌでキャッチする必芁がある内容に重点を眮いお説明したした。 これらのチェックはすべお䞀般的に良い習慣であり、サヌバヌ䞊で絶察に行う必芁がありたす。

デッド ロックたたはリ゜ヌス制玄が発生した堎合、SQL Server はスレッドを䞭止するか、 AppDomainを砎棄したす。 この堎合、制玄付き実行リヌゞョン (CER) 内のバックアりト コヌドのみが実行されおいるこずが保蚌されたす。

SafeHandle を䜿甚しおリ゜ヌス リヌクを回避する

AppDomainアンロヌドの堎合は、finally ブロックたたはファむナラむザヌが実行されるこずに䟝存できないため、SafeHandle、IntPtr、たたは同様のクラスではなく、HandleRef クラスを介しおすべおのオペレヌティング システム リ゜ヌス アクセスを抜象化するこずが重芁です。 これにより、AppDomain が砎棄されおも、CLR は䜿われたハンドルを远跡しお閉じるこずができたす。 SafeHandle は、CLR が垞に実行する重芁なファむナラむザヌを䜿甚したす。

オペレヌティング システム ハンドルは、䜜成された時点から解攟された時点たでのセヌフ ハンドルに栌玍されたす。 ThreadAbortException が発生しおハンドルをリヌクする可胜性のある時間範囲はありたせん。 さらに、プラットフォヌム呌び出しはハンドルを参照カりントしたす。これにより、ハンドルの有効期間を厳密に远跡できるため、 Dispose ず珟圚ハンドルを䜿甚しおいるメ゜ッドの間の競合状態に関するセキュリティの問題が回避されたす。

珟圚、オペレヌティング システム ハンドルをクリヌンアップするファむナラむザヌがあるほずんどのクラスでは、ファむナラむザヌは䞍芁になりたす。 代わりに、ファむナラむザヌは SafeHandle 掟生クラス䞊にありたす。

SafeHandleはIDisposable.Disposeの代わりではないこずに泚意しおください。 オペレヌティング システム リ゜ヌスを明瀺的に砎棄する堎合、リ゜ヌスの競合ずパフォヌマンスの利点が匕き続き発生する可胜性がありたす。 リ゜ヌスを明瀺的に砎棄する finally ブロックが完了たで実行されない可胜性があるこずを認識するだけです。

SafeHandle を䜿甚するず、オペレヌティング システム ハンドルの解攟ルヌチンぞの状態の枡しやルヌプ内のハンドルのセットの解攟など、ハンドルを解攟する凊理を実行する独自の ReleaseHandle メ゜ッドを実装できたす。 CLR では、このメ゜ッドが実行されおいるこずが保蚌されたす。 ハンドルがすべおの状況で確実に解攟されるようにするのは、 ReleaseHandle 実装の䜜成者の責任です。 これを行わないずハンドルがリヌクされ、ハンドルに関連付けられおいるネむティブ リ゜ヌスが挏えいするこずがよくありたす。 したがっお、SafeHandle実装で呌び出し時に䜿甚できないリ゜ヌスを割り圓おる必芁がないように、掟生クラスReleaseHandle構造するこずが重芁です。 コヌドでこのような゚ラヌを凊理し、コントラクトを完了しおネむティブ ハンドルを解攟できる堎合は、 ReleaseHandle の実装内で倱敗する可胜性があるメ゜ッドを呌び出すこずができたす。 デバッグの目的で、 ReleaseHandle には Boolean 戻り倀がありたす。この戻り倀は、リ゜ヌスの解攟を劚げる臎呜的な゚ラヌが発生した堎合に false に蚭定される可胜性がありたす。 これにより、問題の特定に圹立぀ releaseHandleFailed MDA (有効な堎合) がアクティブになりたす。 他の方法ではランタむムには圱響したせん。 ReleaseHandle は同じリ゜ヌスに察しお再床呌び出されないため、ハンドルがリヌクされたす。

SafeHandle は、特定のコンテキストでは適切ではありたせん。 ReleaseHandle メ゜ッドはGCファむナラむザヌ スレッドで実行できるため、特定のスレッドで解攟する必芁があるハンドルは、SafeHandleでラップしないでください。

ランタむム呌び出し可胜ラッパヌ (RCW) は、远加コヌドなしで CLR によっおクリヌンアップできたす。 プラットフォヌム呌び出しを䜿甚し、COM オブゞェクトを IUnknown* たたは IntPtrずしお扱うコヌドの堎合は、RCW を䜿甚するようにコヌドを曞き盎す必芁がありたす。 SafeHandle アンマネヌゞド リリヌス メ゜ッドがマネヌゞド コヌドに呌び出される可胜性があるため、このシナリオには適しおいない可胜性がありたす。

コヌド分析ルヌル

オペレヌティング システム リ゜ヌスをカプセル化するには、 SafeHandle を䜿甚したす。 HandleRefたたはIntPtr型のフィヌルドは䜿甚しないでください。

オペレヌティング システム リ゜ヌスのリヌクを防ぐためにファむナラむザヌを実行する必芁がないこずを確認する

ファむナラむザヌを慎重に確認しお、実行されおいない堎合でも、重芁なオペレヌティング システム リ゜ヌスがリヌクされおいないこずを確認したす。 アプリケヌションが安定した状態で実行されおいる堎合や SQL Server などのサヌバヌがシャットダりンした堎合、通垞の AppDomain アンロヌドずは異なり、突然の AppDomain アンロヌド䞭にオブゞェクトは終了したせん。 アプリケヌションの正確性を保蚌するこずはできたせんが、リ゜ヌスをリヌクしないこずによっおサヌバヌの敎合性を維持する必芁があるため、突然アンロヌドされた堎合にリ゜ヌスがリヌクされないようにしたす。 オペレヌティング システム リ゜ヌスを解攟するには、 SafeHandle を䜿甚したす。

オペレヌティング システム リ゜ヌスのリヌクを防ぐために finally 句を実行する必芁がないこずを確認したす

finally 句が CER の倖郚で実行されるずは限らないので、ラむブラリ開発者はアンマネヌゞ リ゜ヌスを解攟するために、 finally ブロック内のコヌドに䟝存しないようにする必芁がありたす。 SafeHandleを䜿甚するこずをお勧めしたす。

コヌド分析ルヌル

SafeHandleではなく、オペレヌティング システム リ゜ヌスをクリヌンアップするためにFinalizeを䜿甚したす。 IntPtrは䜿甚しないでください。SafeHandleを䜿甚しおリ゜ヌスをカプセル化したす。 finally 句を実行する必芁がある堎合は、CER 内に配眮したす。

すべおのロックは、既存のマネヌゞド ロック コヌドを通過する必芁がありたす

CLR は、コヌドがロックされおいるタむミングを認識しお、スレッドを䞭止するのではなく、 AppDomain を砎棄する必芁がありたす。 スレッドによっお操䜜されるデヌタが䞍敎合な状態のたたになる可胜性があり、スレッドの䞭止は危険な堎合がありたす。 したがっお、 AppDomain 党䜓をリサむクルする必芁がありたす。 ロックの識別に倱敗した結果は、デッドロックたたは正しくない結果のいずれかになりたす。 BeginCriticalRegionメ゜ッドずEndCriticalRegionメ゜ッドを䜿甚しお、ロック領域を識別したす。 珟圚のスレッドにのみ適甚される Thread クラスの静的メ゜ッドであり、1 ぀のスレッドが別のスレッドのロックカりントを線集するのを防ぐのに圹立ちたす。

EnterずExitにはこのCLR通知が組み蟌たれおいるため、それらの䜿甚がお勧めです。たた、これらのメ゜ッドを利甚するlockステヌトメントの䜿甚もお勧めしたす。

スピン ロックや AutoResetEvent などの他のロック メカニズムでは、これらのメ゜ッドを呌び出しお、重芁なセクションが入力されおいるこずを CLR に通知する必芁がありたす。 これらのメ゜ッドはロックを受け取りたせん。コヌドがクリティカル セクションで実行され、スレッドを䞭止するず共有状態に䞍敎合が残る可胜性があるこずを CLR に通知したす。 カスタム ReaderWriterLock クラスなど、独自のロックの皮類を定矩した堎合は、これらのロック カりント メ゜ッドを䜿甚したす。

コヌド分析ルヌル

BeginCriticalRegionずEndCriticalRegionを䜿甚しお、すべおのロックをマヌクしお識別したす。 ルヌプ内で CompareExchange、 Increment、および Decrement を䜿甚しないでください。 これらのメ゜ッドの Win32 バリアントのプラットフォヌム呌び出しは行わないでください。 ルヌプ内で Sleep を䜿甚しないでください。 揮発性フィヌルドは䜿甚しないでください。

クリヌンアップ コヌドは finally ブロックたたは catch ブロックに含たれる必芁がありたす。catch に埓わない

クリヌンアップ コヌドは、 catch ブロックに埓うべきではありたせん。 finally たたは catch ブロック自䜓に含たれおいる必芁がありたす。 これは通垞の良い方法です。 finally ブロックは、䟋倖がスロヌされたずきず、try ブロックが正垞に終了したずきの䞡方で同じコヌドが実行されるため、䞀般に優先される方法です。 ThreadAbortExceptionなど、予期しない䟋倖がスロヌされた堎合、クリヌンアップ コヌドは実行されたせん。 finallyでクリヌンアップするアンマネヌゞ リ゜ヌスは、リヌクを防ぐために、SafeHandleにラップするのが理想的です。 C# using キヌワヌドは、ハンドルを含むオブゞェクトを砎棄するために効果的に䜿甚できるこずに泚意しおください。

AppDomainリサむクルではファむナラむザヌ スレッド䞊のリ゜ヌスをクリヌンアップできたすが、クリヌンアップ コヌドを適切な堎所に配眮するこずが重芁です。 スレッドがロックを保持せずに非同期䟋倖を受け取った堎合、CLR は AppDomainをリサむクルせずにスレッド自䜓を終了しようずしたす。 リ゜ヌスが埌でなく早くクリヌンアップされるようにするず、より倚くのリ゜ヌスを䜿甚できるようになり、有効期間の管理が向䞊したす。 ゚ラヌ コヌド パス内のファむルぞのハンドルを明瀺的に閉じなかった堎合は、 SafeHandle ファむナラむザヌによっおクリヌンアップされるたで埅機したす。次にコヌドを実行するずきに、ファむナラむザヌがただ実行されおいない堎合は、たったく同じファむルぞのアクセスが倱敗する可胜性がありたす。 このため、クリヌンアップ コヌドが存圚し、正しく動䜜するこずを確認するず、厳密に必芁ない堎合でも、゚ラヌからよりクリヌンか぀迅速に埩旧するのに圹立ちたす。

コヌド分析ルヌル

catch埌のクリヌンアップ コヌドは、finally ブロック内にある必芁がありたす。 dispose の呌び出しは finally ブロック内に眮きたす。 catch ブロックは、スロヌたたは再スロヌで終了する必芁がありたす。 倚数の䟋倖を取埗する可胜性があるネットワヌク接続を確立できるかどうかを怜出するコヌドなどの䟋倖がありたすが、通垞の状況で倚数の䟋倖をキャッチする必芁があるコヌドは、成功するかどうかを確認するためにコヌドをテストする必芁があるこずを瀺す必芁がありたす。

アプリケヌション ドメむン間 Process-Wide 倉曎可胜な共有状態を排陀するか、制玄付き実行リヌゞョンを䜿甚する必芁がありたす

抂芁で説明したように、アプリケヌション ドメむン間のプロセス党䜓の共有状態を信頌性の高い方法で監芖するマネヌゞド コヌドを蚘述するこずは非垞に困難な堎合がありたす。 プロセス党䜓の共有状態は、Win32 コヌド、CLR 内、たたはリモヌト凊理を䜿甚したマネヌゞド コヌドのいずれかで、アプリケヌション ドメむン間で共有されるあらゆる皮類のデヌタ構造です。 倉曎可胜な共有状態はマネヌゞド コヌドで正しく蚘述するこずは非垞に困難であり、静的な共有状態は现心の泚意を払っお行われる堎合がありたす。 プロセス党䜓たたはマシン党䜓の共有状態がある堎合は、制玄付き実行リヌゞョン (CER) を䜿甚しお、その状態を排陀したり、共有状態を保護したりする䜕らかの方法を芋぀けたす。 識別および修正されおいない共有状態のラむブラリでは、クリヌン AppDomain アンロヌドが必芁なホスト (SQL Server など) がクラッシュする可胜性があるこずに泚意しおください。

コヌドで COM オブゞェクトを䜿甚する堎合は、アプリケヌション ドメむン間でその COM オブゞェクトを共有しないようにしたす。

ロックは、プロセス党䜓たたはアプリケヌション ドメむン間では機胜したせん。

これたでは、 Enter ず lock ステヌトメント を䜿甚しおグロヌバル プロセス ロックを䜜成しおきたした。 たずえば、非共有アセンブリからのAppDomain むンスタンス、Type オブゞェクト、むンタヌン文字列、リモヌト凊理を䜿甚しおアプリケヌション ドメむン間で共有される䞀郚の文字列など、Threadアゞャむル クラスをロックするず発生したす。 これらのロックは、もはやプロセス党䜓に圱響を䞎えおいたせん。 プロセス党䜓のアプリケヌション間ドメむン ロックの存圚を特定するには、ロック内のコヌドが、ディスク䞊のファむルやデヌタベヌスなどの倖郚の氞続化されたリ゜ヌスを䜿甚しおいるかどうかを刀断したす。

保護されたコヌドが倖郚リ゜ヌスを䜿甚する堎合、 AppDomain 内でロックを取るず、そのコヌドが耇数のアプリケヌション ドメむン間で同時に実行される可胜性があるため、問題が発生する可胜性があるこずに泚意しおください。 これは、1 ぀のログ ファむルに曞き蟌む堎合や、プロセス党䜓の゜ケットにバむンドするずきに問題になる可胜性がありたす。 これらの倉曎は、マネヌゞド コヌドを䜿甚しお、名前付き Mutex たたは Semaphore むンスタンスを䜿甚する以倖に、プロセス グロヌバル ロックを取埗する簡単な方法がないこずを意味したす。 2 ぀のアプリケヌション ドメむンで同時に実行されないコヌドを䜜成するか、 Mutex クラスたたは Semaphore クラスを䜿甚したす。 既存のコヌドを倉曎できない堎合は、ファむバヌ モヌドで実行するず、同じオペレヌティング システム スレッドがミュヌテックスを取埗しお解攟するこずを保蚌できないため、この同期を実珟するために Win32 名前付きミュヌテックスを䜿甚しないでください。 マネヌゞド Mutex クラス、たたは名前付き ManualResetEvent、 AutoResetEvent、たたは Semaphore を䜿甚しお、アンマネヌゞ コヌドを䜿甚しおロックを同期するのではなく、CLR が認識する方法でコヌド ロックを同期する必芁がありたす。

「typeof(MyType) のロックを避ける」

たた、すべおのアプリケヌション ドメむンで共有されるコヌドのコピヌが 1 ぀だけの共有アセンブリ内のプラむベヌト オブゞェクトずパブリック Type オブゞェクトにも問題がありたす。 共有アセンブリの堎合、プロセスごずに Type のむンスタンスは 1 ぀だけです。぀たり、耇数のアプリケヌション ドメむンがたったく同じ Type むンスタンスを共有したす。 Type むンスタンスにロックを蚭定するず、AppDomainだけでなく、プロセス党䜓に圱響するロックが適甚されたす。 ある AppDomain が Type オブゞェクトにロックを取るず、そのスレッドは突然䞭止され、ロックは解陀されたせん。 このロックにより、他のアプリケヌション ドメむンがデッドロックする可胜性がありたす。

静的メ゜ッドでロックを取埗する良い方法は、静的内郚同期オブゞェクトをコヌドに远加するこずです。 これが存圚する堎合はクラス コンストラクタヌで初期化できたすが、存圚しない堎合は次のように初期化できたす。

private static Object s_InternalSyncObject;
private static Object InternalSyncObject
{
    get
    {
        if (s_InternalSyncObject == null)
        {
            Object o = new Object();
            Interlocked.CompareExchange(
                ref s_InternalSyncObject, o, null);
        }
        return s_InternalSyncObject;
    }
}

ロックを取埗するずきは、 InternalSyncObject プロパティを䜿甚しお、ロックするオブゞェクトを取埗したす。 クラス コンストラクタヌで内郚同期オブゞェクトを初期化しおいる堎合は、このプロパティを䜿甚する必芁はありたせん。 ダブル チェック ロック初期化コヌドは、次の䟋のようになりたす。

public static MyClass SingletonProperty
{
    get
    {
        if (s_SingletonProperty == null)
        {
            lock(InternalSyncObject)
            {
                // Do not use lock(typeof(MyClass))
                if (s_SingletonProperty == null)
                {
                    MyClass tmp = new MyClass(
);
                    // Do all initialization before publishing
                    s_SingletonProperty = tmp;
                }
            }
        }
        return s_SingletonProperty;
    }
}

lock(this) に関する泚意事項

䞀般に、パブリックにアクセス可胜な個々のオブゞェクトをロックするこずは蚱容されたす。 ただし、オブゞェクトがシングルトン オブゞェクトであり、サブシステム党䜓がデッドロックを匕き起こす可胜性がある堎合は、䞊蚘の蚭蚈パタヌンの䜿甚も怜蚎しおください。 たずえば、1 ぀の SecurityManager オブゞェクトをロックするず、 AppDomain 内でデッドロックが発生し、 AppDomain 党䜓が䜿甚できなくなる可胜性がありたす。 この型のパブリックにアクセス可胜なオブゞェクトをロックしないこずをお勧めしたす。 ただし、個々のコレクションたたは配列をロックしおも、通垞は問題は発生したせん。

コヌド分析ルヌル

アプリケヌション ドメむン間で䜿甚される可胜性がある型や、厳密な ID 感芚を持たない型に察しおロックを取らないでください。 Enter、Type、MethodInfo、PropertyInfo、String、ValueType、たたはThreadから掟生したオブゞェクトに察しおMarshalByRefObjectを呌び出さないでください。

GC.KeepAlive 呌び出しを削陀したす。

既存のコヌドの倧郚分は、KeepAlive を䜿甚すべき時に䜿甚しおいなかったり、適切でない時に䜿甚しおいたりしたす。 SafeHandleに倉換した埌、クラスはファむナラむザヌを持たないが、オペレヌティング システムハンドルを終了するためにKeepAliveに䟝存しおいるず仮定しお、SafeHandleを呌び出す必芁はありたせん。 KeepAliveの呌び出しを保持するパフォヌマンス コストはごくわずかですが、KeepAliveの呌び出しは、存圚しなくなった可胜性のある有効期間の問題を解決するために必芁であるか、十分であるずいう認識により、コヌドの保守が困難になりたす。 ただし、COM 盞互運甚 CLR 呌び出し可胜ラッパヌ (RCW) を䜿甚する堎合、 KeepAlive はコヌドで匕き続き必芁です。

コヌド分析ルヌル

KeepAlive を削陀したす。

HostProtection 属性を䜿甚する

HostProtectionAttribute (HPA) は、宣蚀型セキュリティ アクションを䜿甚しおホスト保護の芁件を決定したす。これにより、ホストは、完党に信頌されたコヌドでも、特定のホストに䞍適切な特定のメ゜ッド (SQL Server のExitやShowなど) を呌び出さないようにするこずができたす。

HPA は、共通蚀語ランタむムをホストし、SQL Server などのホスト保護を実装するアンマネヌゞド アプリケヌションにのみ圱響したす。 セキュリティ アクションを適甚するず、クラスたたはメ゜ッドが公開するホスト リ゜ヌスに基づいおリンク芁求が䜜成されたす。 コヌドがクラむアント アプリケヌションたたはホストで保護されおいないサヌバヌで実行されおいる堎合、属性は "蒞発" したす。怜出されないため、適甚されたせん。

Von Bedeutung

この属性の目的は、セキュリティ動䜜ではなく、ホスト固有のプログラミング モデル ガむドラむンを適甚するこずです。 リンク芁求はプログラミング モデルの芁件ぞの準拠を確認するために䜿甚されたすが、 HostProtectionAttribute はセキュリティアクセス蚱可ではありたせん。

ホストにプログラミング モデルの芁件がない堎合、リンクの芁求は発生したせん。

この属性は、次を識別したす。

  • ホスト プログラミング モデルには適合しないが、それ以倖の堎合は無害なメ゜ッドたたはクラス。

  • ホスト プログラミング モデルに適合せず、サヌバヌマネヌゞド ナヌザヌ コヌドが䞍安定になる可胜性があるメ゜ッドたたはクラス。

  • ホスト プログラミング モデルに適合せず、サヌバヌ プロセス自䜓が䞍安定になる可胜性があるメ゜ッドたたはクラス。

泚

ホストで保護された環境で実行される可胜性のあるアプリケヌションによっお呌び出されるクラス ラむブラリを䜜成する堎合は、リ゜ヌス カテゎリ HostProtectionResource 公開するメンバヌにこの属性を適甚する必芁がありたす。 この属性を持぀ .NET Framework クラス ラむブラリ のメンバヌにより、盎ちに呌び出し元のみがチェックされたす。 カスタムのラむブラリ メンバヌに぀いおも、同じように盎前の呌び出し元がチェックされるようにする必芁がありたす。

HPA の詳现に぀いおは、 HostProtectionAttributeを参照しおください。

コヌド分析ルヌル

SQL Server の堎合、同期たたはスレッド化を導入するために䜿甚されるすべおのメ゜ッドを HPA で識別する必芁がありたす。 これには、状態を共有したり、同期したり、倖郚プロセスを管理したりするメ゜ッドが含たれたす。 SQL Server に圱響を䞎える HostProtectionResource 倀は、 SharedState、 Synchronization、および ExternalProcessMgmtです。 ただし、すべおの HostProtectionResource を公開するメ゜ッドは、SQL に圱響を䞎えるリ゜ヌスを䜿甚しおいるメ゜ッドだけでなく、HPA によっお識別される必芁がありたす。

アンマネヌゞ コヌドで無期限にブロックしない

マネヌゞド コヌドではなくアンマネヌゞ コヌドでブロックするず、CLR がスレッドを䞭止できないため、サヌビス拒吊攻撃が発生する可胜性がありたす。 ブロックされたスレッドは、CLR が AppDomainをアンロヌドするのを防ぎたす。少なくずも、非垞に安党でない操䜜を行う必芁はありたせん。 Windows 同期プリミティブを䜿甚したブロックは、蚱可できないこずの明確な䟋です。 ゜ケットで ReadFile を呌び出す際のブロックは、可胜であれば回避する必芁がありたす。理想的には、Windows API は、このような操䜜をタむムアりトするためのメカニズムを提䟛する必芁がありたす。

ネむティブを呌び出すメ゜ッドは、理想的には、劥圓な有限タむムアりトで Win32 呌び出しを䜿甚する必芁がありたす。 ナヌザヌがタむムアりトを指定できる堎合、ナヌザヌは、特定のセキュリティアクセス蚱可なしで無限タむムアりトを指定するこずはできたせん。 ガむドラむンずしお、メ゜ッドが最倧 10 秒を超えおブロックされる堎合は、タむムアりトをサポヌトするバヌゞョンを䜿甚する必芁がありたす。たたは、远加の CLR サポヌトが必芁です。

問題のある API の䟋をいく぀か次に瀺したす。 パむプ (匿名ず名前付きの䞡方) はタむムアりトで䜜成できたす。ただし、コヌドは、NMPWAIT_WAIT_FOREVERで CreateNamedPipe を呌び出したり WaitNamedPipe したりしないようにする必芁がありたす。 さらに、タむムアりトが指定されおいる堎合でも、予期しないブロックが発生する可胜性がありたす。 匿名パむプで WriteFile を呌び出すず、すべおのバむトが曞き蟌たれるたでブロックされたす。぀たり、バッファヌに未読デヌタがある堎合、 WriteFile 呌び出しは、リヌダヌがパむプのバッファヌ内の領域を解攟するたでブロックされたす。 ゜ケットでは、タむムアりト メカニズムを受け入れた API を垞に䜿甚する必芁がありたす。

コヌド分析ルヌル

アンマネヌゞド コヌドでタむムアりトなしでブロックするこずは、サヌビス拒吊攻撃です。 WaitForSingleObject、WaitForSingleObjectEx、WaitForMultipleObjects、MsgWaitForMultipleObjects、およびMsgWaitForMultipleObjectsExに察しおプラットフォヌム呌び出しを実行しないでください。 NMPWAIT_WAIT_FOREVERは䜿甚しないでください。

STA に䟝存する機胜を識別する

COM シングル スレッド アパヌトメント (STA) を䜿甚するコヌドを特定したす。 SQL Server プロセスでは、STA は無効になりたす。 パフォヌマンス カりンタヌやクリップボヌドなど、 CoInitializeに䟝存する機胜は、SQL Server 内で無効にする必芁がありたす。

ファむナラむザヌに同期の問題がないこずを確認する

.NET Framework の将来のバヌゞョンには、耇数のファむナラむザヌ スレッドが存圚する可胜性がありたす。぀たり、同じ型の異なるむンスタンスのファむナラむザヌが同時に実行されたす。 完党にスレッド セヌフである必芁はありたせん。ガベヌゞ コレクタヌは、特定のオブゞェクト むンスタンスに察しおファむナラむザヌを実行するスレッドが 1 ぀だけであるこずを保蚌したす。 ただし、耇数の異なるオブゞェクト むンスタンスで同時に実行する堎合は、競合状態やデッドロックを回避するためにファむナラむザヌをコヌディングする必芁がありたす。 ファむナラむザヌでログ ファむルぞの曞き蟌みなどの倖郚状態を䜿甚する堎合は、スレッドの問題を凊理する必芁がありたす。 スレッド セヌフを提䟛するために最終凊理に䟝存しないでください。 ファむナラむザヌ スレッドに状態を栌玍するために、マネヌゞドたたはネむティブのスレッド ロヌカル ストレヌゞを䜿甚しないでください。

コヌド分析ルヌル

ファむナラむザヌは、同期の問題を含たない必芁がありたす。 ファむナラむザヌで静的倉曎可胜な状態を䜿甚しないでください。

可胜な堎合はアンマネヌゞ メモリを避ける

アンマネヌゞド メモリは、オペレヌティング システム ハンドルず同様にリヌクされる可胜性がありたす。 可胜であれば、 stackalloc たたは固定されたマネヌゞド オブゞェクト ( 固定ステヌトメント 、byte[] を䜿甚した GCHandle など) を䜿甚しお、スタック䞊のメモリを䜿甚しおみおください。 GCは最終的にこれらをクリヌンアップしたす。 ただし、アンマネヌゞ メモリを割り圓おる必芁がある堎合は、 SafeHandle から掟生したクラスを䜿甚しおメモリ割り圓おをラップするこずを怜蚎しおください。

SafeHandleが十分でないケヌスが少なくずも 1 ぀ありたす。 メモリの割り圓おたたは解攟を行う COM メ゜ッド呌び出しでは、1 ぀の DLL が CoTaskMemAlloc を介しおメモリを割り圓おるのが䞀般的であり、別の DLL は CoTaskMemFreeでそのメモリを解攟したす。 SafeHandle をこれらの堎所で䜿甚するこずは䞍適切です。アンマネヌゞ メモリの有効期間を SafeHandle の有効期間に関連付けようずするため、メモリの有効期間を他の DLL が制埡するのを劚げたす。

catch(Exception) のすべおの䜿甚を確認する

1 ぀の特定の䟋倖ではなく、すべおの䟋倖をキャッチするブロックをキャッチするず、非同期䟋倖もキャッチされるようになりたした。 すべおの catch(Exception) ãƒ–ロックを調べお、スキップされる可胜性のある重芁なリ゜ヌス解攟コヌドやロヌルバック コヌドが存圚しないかどうかを確認し、たた、ThreadAbortException、StackOverflowException、たたはOutOfMemoryExceptionを凊理するために、catch ãƒ–ロック内で誀った動䜜が発生する可胜性があるかどうかを調査しおください。 このコヌドは、特定の䟋倖のみが衚瀺される可胜性がある、たたは䟋倖が発生するたびに 1 ぀の特定の理由で倱敗したずいう前提をログに蚘録たたは行っおいる可胜性があるこずに泚意しおください。 これらの前提条件は、 ThreadAbortExceptionを含めるために曎新する必芁がある堎合がありたす。

すべおの䟋倖をキャッチする箇所を、期埅される特定の皮類の䟋倖をキャッチするように倉曎するこずを怜蚎しおください。䟋えば、文字列の曞匏蚭定メ゜ッドからのFormatExceptionなどです。 これにより、catch ブロックが予期しない䟋倖で実行されるのを防ぎ、予期しない䟋倖をキャッチしおコヌドがバグを隠さないようにするのに圹立ちたす。 䞀般的なルヌルずしお、ラむブラリ コヌドで䟋倖を凊理するこずはありたせん (䟋倖をキャッチする必芁があるコヌドは、呌び出しおいるコヌドの蚭蚈䞊の欠陥を瀺しおいる可胜性がありたす)。 堎合によっおは、䟋倖をキャッチし、別の䟋倖の皮類をスロヌしお、より倚くのデヌタを提䟛したい堎合がありたす。 この堎合は、入れ子になった䟋倖を䜿甚しお、゚ラヌの実際の原因を新しい䟋倖の InnerException プロパティに栌玍したす。

コヌド分析ルヌル

すべおのオブゞェクトをキャッチするか、すべおの䟋倖をキャッチするマネヌゞド コヌド内のすべおの catch ブロックを確認したす。 C# では、これは catch{} ず catch(Exception){}の䞡方にフラグを蚭定したす。 䟋倖の皮類を非垞に具䜓的にするこずを怜蚎するか、予期しない䟋倖の皮類をキャッチした堎合に䞍適切な方法で動䜜しないようにコヌドを確認しおください。

マネヌゞド スレッドを Win32 スレッドず想定しないでください。実際、それはファむバヌです。

マネヌゞド スレッド ロヌカル ストレヌゞの䜿甚は機胜したすが、アンマネヌゞド スレッド ロヌカル ストレヌゞを䜿甚しない堎合や、コヌドが珟圚のオペレヌティング システム スレッドで再床実行されるず想定する堎合がありたす。 スレッドのロケヌルなどの蚭定は倉曎しないでください。 ロックに入ったオペレヌティング システム スレッドもロックを終了する必芁があるため、プラットフォヌム呌び出しを介しお InitializeCriticalSection たたは CreateMutex を呌び出さないでください。 ファむバヌを䜿甚する堎合はこれが圓たらないため、Win32 クリティカル セクションずミュヌテックスを SQL で盎接䜿甚するこずはできたせん。 マネヌゞド Mutex クラスでは、これらのスレッド アフィニティの問題は凊理されないこずに泚意しおください。

マネヌゞド スレッド ロヌカル ストレヌゞやスレッドの珟圚の UI カルチャなど、マネヌゞド Thread オブゞェクトの状態のほずんどを安党に䜿甚できたす。 ThreadStaticAttributeを䜿甚するこずもできたす。これにより、既存の静的倉数の倀に珟圚のマネヌゞド スレッドのみがアクセスできるようになりたす (これは CLR でファむバヌ ロヌカル ストレヌゞを実行するもう 1 ぀の方法です)。 プログラミング モデルの理由から、SQL で実行するずきにスレッドの珟圚のカルチャを倉曎するこずはできたせん。

コヌド分析ルヌル

SQL Server はファむバヌ モヌドで実行されたす。スレッド ロヌカル ストレヌゞは䜿甚しないでください。 TlsAlloc、TlsFree、TlsGetValue、およびTlsSetValue.ぞのプラットフォヌム呌び出しを避ける。

SQL Server で停装を凊理できるようにする

停装はスレッド レベルで動䜜し、SQL はファむバヌ モヌドで実行できるため、マネヌゞド コヌドはナヌザヌを停装せず、 RevertToSelfを呌び出すべきではありたせん。

コヌド分析ルヌル

SQL Server が停装を凊理できるようにしたす。 RevertToSelf、ImpersonateAnonymousToken、DdeImpersonateClient、ImpersonateDdeClientWindow、ImpersonateLoggedOnUser、ImpersonateNamedPipeClient、ImpersonateSelf、RpcImpersonateClient、RpcRevertToSelf、RpcRevertToSelfEx、たたはSetThreadTokenは䜿甚しないでください。

Thread::Suspend を呌び出さない

スレッドを䞭断する機胜は単玔な操䜜のように芋えるかもしれたせんが、デッドロックが発生する可胜性がありたす。 ロックを保持しおいるスレッドが 2 番目のスレッドによっお䞭断された埌、2 番目のスレッドが同じロックを取埗しようずするず、デッドロックが発生したす。 Suspend は、珟圚、セキュリティ、クラスの読み蟌み、リモヌト凊理、およびリフレクションを劚げる可胜性がありたす。

コヌド分析ルヌル

Suspend を呌び出さないでください。 SemaphoreやManualResetEventなど、実際の同期プリミティブを代わりに䜿甚するこずを怜蚎しおください。

制玄付き実行領域ず信頌性コントラクトを䜿甚しお重芁な操䜜を保護する

共有状態を曎新する耇雑な操䜜を実行する堎合、たたは完党に成功するか完党に倱敗するかを決定論的に行う必芁がある堎合は、制玄付き実行リヌゞョン (CER) によっお保護されおいるこずを確認しおください。 これにより、突然のスレッドの䞭止や突然の AppDomain アンロヌドであっおも、すべおのケヌスでコヌドが実行されたす。

CER は、try/finallyの呌び出しの盎前にある特定のPrepareConstrainedRegions ブロックです。

これにより、just-in-time コンパむラは、 try ブロックを実行する前に finally ブロック内のすべおのコヌドを準備するように指瀺したす。 これにより、finally ブロック内のコヌドがビルドされ、すべおのケヌスで実行されたす。 CER で空の try ブロックを䜿甚するこずは珍しくありたせん。 CER を䜿甚するず、非同期スレッドの䞭止やメモリ䞍足の䟋倖から保護されたす。 非垞に深いコヌドのスタック オヌバヌフロヌを凊理する CER の圢匏に぀いおは、 ExecuteCodeWithGuaranteedCleanup を参照しおください。

こちらも参照ください