Güvenilirlik En İyi Yöntemleri
Aşağıdaki güvenilirlik kuralları SQL Server'a yöneliktir; ancak, bunlar herhangi bir konak tabanlı sunucu uygulaması için de geçerlidir. SQL Server gibi sunucuların kaynakları sızdırmaması ve indirilmemesi son derece önemlidir. Ancak bu, bir nesnenin durumunu değiştiren her yöntem için geri çıkış kodu yazılarak yapılamaz. Hedef, geri alma koduyla her konumdaki hatalardan kurtarılacak yüzde 100 güvenilir yönetilen kod yazmak değildir. Bu, başarı şansı az olan göz korkutucu bir görev olurdu. Ortak dil çalışma zamanı (CLR), mükemmel kod yazmayı mümkün hale getirmek için yönetilen kod için yeterince güçlü garantiler sağlamaz. sql server ASP.NET aksine, kabul edilemez uzun bir süre için bir veritabanı indirilmeden geri dönüştürülemez tek bir işlem kullanır unutmayın.
Bu daha zayıf garantiler ve tek bir işlemde çalışırken güvenilirlik, gerektiğinde iş parçacıklarını sonlandırmaya veya uygulama etki alanlarını geri dönüştürmeye ve tanıtıcılar veya bellek gibi işletim sistemi kaynaklarının sızdırılmamasını sağlamak için önlemler almaya dayanır. Bu daha basit güvenilirlik kısıtlamasıyla bile önemli bir güvenilirlik gereksinimi vardır:
İşletim sistemi kaynaklarını asla sızdırmayın.
CLR'ye yönelik tüm formlardaki tüm yönetilen kilitleri tanımlayın.
Uygulamalar arası etki alanı paylaşılan durumunu asla kesmeyin ve geri dönüşümün AppDomain sorunsuz çalışmasını sağlayın.
, StackOverflowExceptionve OutOfMemoryException özel durumlarını işlemek ThreadAbortExceptioniçin yönetilen kod yazmak teorik olarak mümkün olsa da geliştiricilerin uygulamanın tamamında bu kadar sağlam kod yazmasını beklemek mantıksızdır. Bu nedenle bant dışı özel durumlar yürütme iş parçacığının sonlandırılmasıyla sonuçlanır; ve sonlandırılan iş parçacığı paylaşılan durumu düzenliyorsa, bu durum iş parçacığının bir kilit barındırıp tutmadığı tarafından belirlenebilir, sonra AppDomain kaldırılır. Paylaşılan durumu düzenleyen bir yöntem sonlandırıldığında, paylaşılan duruma güncelleştirmeler için güvenilir geri alma kodu yazmak mümkün olmadığından durum bozulur.
.NET Framework sürüm 2.0'da güvenilirlik gerektiren tek konak SQL Server'dır. Derlemeniz SQL Server'da çalıştırılacaksa, veritabanında çalıştırılırken devre dışı bırakılan belirli özellikler olsa bile bu derlemenin her bölümü için güvenilirlik çalışması yapmanız gerekir. Kod çözümleme altyapısı kodu derleme düzeyinde incelediğinden ve devre dışı bırakılmış kodu ayırt edemeyeceğinden bu gereklidir. Sql Server programlamada dikkat edilmesi gereken bir diğer nokta da SQL Server'ın her şeyi tek bir işlemde çalıştırması ve AppDomain geri dönüştürmenin bellek ve işletim sistemi tanıtıcıları gibi tüm kaynakları temizlemek için kullanılmasıdır.
Geri çıkış kodu için sonlandırıcılara, yıkıcılara veya try/finally
bloklara bağımlı olamazsınız. Bunlar kesintiye uğrayabilir veya çağrılmayabilir.
Zaman uyumsuz özel durumlar beklenmeyen konumlarda, büyük olasılıkla her makine yönergesinde oluşturulabilir: ThreadAbortException, StackOverflowExceptionve OutOfMemoryException.
Yönetilen iş parçacıklarının SQL'de Win32 iş parçacıkları olması gerekmez; Lifler olabilir.
İşlem genelinde veya çapraz uygulama etki alanı değiştirilebilir paylaşılan durumunun güvenli bir şekilde değiştirilmesi son derece zordur ve mümkün olduğunda kaçınılmalıdır.
SQL Server'da yetersiz bellek koşulları nadir değildir.
SQL Server'da barındırılan kitaplıklar paylaşılan durumlarını doğru güncelleştirmezse, veritabanı yeniden başlatılana kadar kodun kurtarılmama olasılığı yüksektir. Buna ek olarak, bazı aşırı durumlarda, bu SQL Server işleminin başarısız olmasına ve veritabanının yeniden başlatılmasına neden olabilir. Veritabanını yeniden başlatmak bir Web sitesini çökertebilir veya şirket operasyonlarını etkileyerek kullanılabilirliği olumsuz etkileyebilir. Bellek veya tanıtıcılar gibi işletim sistemi kaynaklarının yavaş sızması, sunucunun kurtarma olasılığı olmayan tanıtıcıları ayırmada başarısız olmasına neden olabilir veya sunucunun performansı yavaş yavaş düşebilir ve müşterinin uygulama kullanılabilirliğini azaltabilir. Bu senaryolardan kaçınmak istediğimiz açıktır.
En iyi yöntem kuralları
Giriş, sunucuda çalışan yönetilen kod için kod incelemesinin çerçevenin kararlılığını ve güvenilirliğini artırmak için yakalaması gereken koda odaklanmıştır. Tüm bu denetimler genel olarak iyi bir uygulamadır ve sunucuda mutlak bir uygulama olmalıdır.
Kilitlenme veya kaynak kısıtlaması karşısında, SQL Server bir iş parçacığını durduracak veya bir AppDomainöğesini yok edecektir. Bu durumda, yalnızca kısıtlanmış yürütme bölgesindeki (CER) geri çıkış kodunun çalıştırılması garanti edilir.
Kaynak sızıntılarını önlemek için Kasa Handle kullanma
Kaldırma durumundaAppDomain, yürütülmekte olan bloklara veya sonlandırıcılara bağımlı finally
olamazsınız, bu nedenle , HandleRefveya benzeri sınıflar yerine IntPtrsınıf aracılığıyla SafeHandle tüm işletim sistemi kaynak erişimini soyutlamanız önemlidir. Bu, CLR'nin yırtılma durumunda bile kullandığınız tutamaçları izlemesine ve kapatmasına AppDomain olanak tanır. SafeHandle , CLR'nin her zaman çalıştıracağı kritik bir sonlandırıcı kullanacaktır.
İşletim sistemi tanıtıcısı, oluşturulduğu andan yayınlandığı ana kadar güvenli tanıtıcıda depolanır. Bir tutamacı sızdıran bir ThreadAbortException pencere yoktur. Buna ek olarak, platform çağrısı tanıtıcıya başvurur ve tanıtıcıyı kullanan bir yöntem arasında Dispose
bir yarış durumuyla ilgili bir güvenlik sorununu önleyerek tanıtıcının ömrünün yakından izlenmesine olanak tanır.
Şu anda bir işletim sistemi tutamacını temizlemek için sonlandırıcısı olan sınıfların çoğu artık sonlandırıcıya ihtiyaç duymayacaktır. Bunun yerine, sonlandırıcı türetilmiş sınıfta olur SafeHandle .
yerine SafeHandle geçilmediğini IDisposable.Disposeunutmayın. İşletim sistemi kaynaklarını açıkça atmak için hala olası kaynak çekişmesi ve performans avantajları vardır. Kaynakları açıkça atan blokların tamamlanmak üzere yürütülemediğini fark edin finally
.
SafeHandle , bir işletim sistemi işleme yordamını serbest duruma geçirme veya bir döngüdeki tanıtıcı kümesini serbest tutma gibi, tanıtıcıyı serbest bıraktıktan sonra işi gerçekleştiren kendi ReleaseHandle yönteminizi uygulamanıza olanak tanır. CLR, bu yöntemin çalıştırılmasını garanti eder. Tanıtıcının her koşulda serbest bırakılmasını sağlamak uygulamanın yazarının ReleaseHandle sorumluluğundadır. Bunun yapılmaması tanıtıcının sızdırılmasına neden olur ve bu da genellikle tanıtıcıyla ilişkili yerel kaynakların sızmasına neden olur. Bu nedenle, türetilmiş sınıflarınReleaseHandle, uygulamanın çağrı zamanında kullanılamayabilecek kaynakların ayrılmasını gerektirmemesi için yapılandırılması SafeHandle kritik önem taşır. Kodunuzun bu tür hataları işleyebileceği ve yerel tanıtıcıyı serbest bırakmak için sözleşmeyi tamamlayabilmesi koşuluyla uygulaması ReleaseHandle içinde başarısız olabilecek yöntemleri çağırmaya izin verildiğini unutmayın. Hata ayıklama amacıyla, ReleaseHandleBoolean kaynağın serbest bırakılmasını engelleyen bir yıkıcı hatayla karşılaşılırsa olarak ayarlanabilecek false
bir dönüş değeri vardır. Bunu yaptığınızda, sorunun tanımlanmasına yardımcı olması için releaseHandleFailed MDA etkinleştirilir. Çalışma zamanını başka bir şekilde etkilemez; ReleaseHandle aynı kaynak için yeniden çağrılmaz ve sonuç olarak tanıtıcı sızdırılır.
SafeHandle belirli bağlamlarda uygun değildir. ReleaseHandle Yöntemi bir sonlandırıcı iş parçacığında çalıştırılabildiği için, belirli bir GC iş parçacığında serbest bırakılırken gereken tüm tanıtıcılar içine SafeHandlesarmalanmamalıdır.
Çalışma zamanı çağrılabilen sarmalayıcılar (RCW) ek kod olmadan CLR tarafından temizlenebilir. Platform çağrısı kullanan ve com nesnesini veya IntPtrolarak IUnknown*
değerlendiren kod için, rcw kullanmak için kodun yeniden yazılması gerekir. SafeHandle yönetilen koda geri çağrı yapan yönetilmeyen bir yayın yöntemi olasılığı nedeniyle bu senaryo için yeterli olmayabilir.
Kod analizi kuralı
İşletim sistemi kaynaklarını kapsüllemek için kullanın SafeHandle . veya türünde IntPtralanlar kullanmayınHandleRef.
İşletim sistemi kaynaklarının sızmasını önlemek için sonlandırıcıların çalıştırılması gerekmediğinden emin olun
Çalışmasalar bile kritik bir işletim sistemi kaynağının sızdırılmadığından emin olmak için sonlandırıcılarınızı dikkatle gözden geçirin. Uygulama sabit bir durumda yürütülürken veya SQL Server gibi bir sunucu kapatıldığında normal AppDomain bir yüklemeden farklı olarak, nesneler ani AppDomain bir kaldırma işlemi sırasında sonlandırılmaz. Ani bir kaldırma durumunda kaynakların sızdırılmadığından emin olun, çünkü uygulamanın doğruluğu garanti edilemez, ancak kaynakların sızdırılmamasıyla sunucunun bütünlüğü korunmalıdır. tüm işletim sistemi kaynaklarını boşaltmak için kullanın SafeHandle .
İşletim sistemi kaynaklarının sızmasını önlemek için finally yan tümcelerinin çalıştırılması gerekmediğinden emin olun
finally
yan tümcelerinin CER'lerin dışında çalıştırılması garanti edilemez ve kitaplık geliştiricilerinin yönetilmeyen kaynakları serbest bırakmaları için bir finally
blok içindeki koda güvenmemesi gerekir. Kullanılması SafeHandle önerilen çözümdür.
Kod analizi kuralı
yerine işletim sistemi kaynaklarını Finalize
temizlemek için kullanınSafeHandle. kullanmayın IntPtr; kaynakları kapsüllemek için kullanın SafeHandle . finally yan tümcesinin çalışması gerekiyorsa, bunu bir CER'ye yerleştirin.
Tüm kilitler mevcut yönetilen kilitleme kodundan geçmelidir
CLR kodun ne zaman kilitte olduğunu bilmeli, böylece iş parçacığını iptal etmek yerine öğesinin yıkılacağını AppDomain bilmelidir. İş parçacığı tarafından çalıştırılan veriler tutarsız bir durumda bırakılabileceğinden iş parçacığının durdurulma durumu tehlikeli olabilir. Bu nedenle, tüm AppDomain geri dönüştürülmek zorunda. Bir kilidin tanımlanamamasının sonuçları kilitlenmeler veya yanlış sonuçlar olabilir. Kilit bölgelerini BeginCriticalRegion tanımlamak için ve EndCriticalRegion yöntemlerini kullanın. Bunlar, sınıfındaki Thread yalnızca geçerli iş parçacığına uygulanan statik yöntemlerdir ve bir iş parçacığının başka bir iş parçacığının kilit sayısını düzenlemesini önlemeye yardımcı olur.
Enterve Exit bu CLR bildirimini yerleşik olarak kullandığınızdan, kullanımlarının yanı sıra bu yöntemleri kullanan lock Deyiminin kullanılması önerilir.
Döndürme kilitleri AutoResetEvent gibi diğer kilitleme mekanizmaları clr'ye kritik bir bölüm girildiğini bildirmek için bu yöntemleri çağırmalıdır. Bu yöntemler herhangi bir kilit almaz; CLR'ye kodun kritik bir bölümde yürütüldüğünü ve iş parçacığını durdurmanın paylaşılan durumu tutarsız bırakabileceğini bildirir. Özel ReaderWriterLock sınıf gibi kendi kilit türünüzü tanımladıysanız, bu kilit sayısı yöntemlerini kullanın.
Kod analizi kuralı
ve kullanarak BeginCriticalRegion tüm kilitleri işaretleyin ve EndCriticalRegiontanımlayın. Bir döngüde , Incrementve Decrement kullanmayınCompareExchange. Bu yöntemlerin Win32 değişkenlerini platform çağrısı yapmayın. Döngüde kullanmayın Sleep . Geçici alanlar kullanmayın.
Temizleme kodu bir finally veya catch bloğunda olmalı, Bir yakalamayı takip etmemelidir
Temizleme kodu hiçbir zaman bir catch
bloğu takip etmemelidir; bloğun catch
içinde finally
veya içinde olmalıdır. Bu normal bir iyi uygulama olmalıdır. Blok finally
genellikle tercih edilir çünkü hem özel durum oluştuğunda hem de bloğun try
sonuna normalde karşılaşıldığında aynı kodu çalıştırır. Beklenmeyen bir özel durum oluştuğunda, örneğin bir ThreadAbortExceptiontemizleme kodu çalışmaz. içinde temizlenecek finally
yönetilmeyen kaynaklar, sızıntıları önlemek için ideal olarak içine SafeHandle sarmalanmalıdır. C# using
anahtar sözcüğünü, tanıtıcılar da dahil olmak üzere nesneleri atmak için etkili bir şekilde kullanabileceğini unutmayın.
Geri dönüşüm, sonlandırıcı iş parçacığındaki kaynakları temizleyebilir, ancak AppDomain temizleme kodunu doğru yere yerleştirmek yine de önemlidir. Bir iş parçacığı kilit tutmadan zaman uyumsuz bir özel durum alırsa, CLR'nin geri dönüşüme gerek kalmadan iş parçacığının kendisini sonlandırmaya çalıştığına AppDomaindikkat edin. Kaynakların daha sonra değil daha önce temizlenmesini sağlamak, daha fazla kaynağın kullanılabilir olmasını sağlayarak ve kullanım ömrünü daha iyi yöneterek yardımcı olur. Bir hata kodu yolundaki bir tanıtıcıyı açıkça kapatmıyorsanız, sonlandırıcının SafeHandle temizlemesini bekleyin; kodunuzun bir sonraki çalıştırmasında, sonlandırıcı henüz çalışmadıysa tam olarak aynı dosyaya erişmeye çalışamayabilir. Bu nedenle, temizleme kodunun mevcut olduğundan ve düzgün çalıştığından emin olmak, kesinlikle gerekli olmasa bile hatalardan daha temiz ve hızlı bir şekilde kurtulmaya yardımcı olur.
Kod analizi kuralı
Bir blokta finally
olması gereken kodu catch
temizleme. Bir finally bloğuna atmak için çağrılar yerleştirin. catch
bloklar bir atma veya yeniden atma ile bitmelidir. Çok sayıda özel durumdan herhangi birini alabileceğiniz bir ağ bağlantısının kurulup kurulamayacağını algılayan kod gibi özel durumlar olsa da, normal koşullarda bir dizi özel durumun yakalanmasını gerektiren tüm kodlar, kodun başarılı olup olmadığını görmek için test edilmesi gerektiğini belirtmelidir.
Uygulama etki alanları arasındaki süreç genelinde değiştirilebilir paylaşılan durum ortadan kaldırılmalı veya kısıtlanmış yürütme bölgesi kullanılmalıdır
Giriş bölümünde açıklandığı gibi, uygulama etki alanları arasında işlem genelinde paylaşılan durumu güvenilir bir şekilde izleyen yönetilen kod yazmak çok zor olabilir. İşlem genelinde paylaşılan durum, Win32 kodunda, CLR'nin içinde veya uzaktan iletişim kullanan yönetilen kodda uygulama etki alanları arasında paylaşılan her tür veri yapısıdır. Herhangi bir değiştirilebilir paylaşılan durumun yönetilen kodda doğru yazılması çok zordur ve statik paylaşılan durum yalnızca büyük bir dikkatle yapılabilir. İşlem genelinde veya makine genelinde paylaşılan durumunuz varsa, bunu ortadan kaldırmanın veya kısıtlanmış yürütme bölgesi (CER) kullanarak paylaşılan durumu korumanın bir yolunu bulun. Kimliği belirlenmemiş ve düzeltilmemiş paylaşılan duruma sahip herhangi bir kitaplığın, temiz AppDomain kaldırma gerektiren SQL Server gibi bir konağın kilitlenmesine neden olabileceğini unutmayın.
Kod bir COM nesnesi kullanıyorsa, bu COM nesnesini uygulama etki alanları arasında paylaşmaktan kaçının.
Kilitler işlem genelinde veya uygulama etki alanları arasında çalışmaz.
Geçmişte ve lock Deyimi genel Enter işlem kilitleri oluşturmak için kullanılmıştır. Örneğin, paylaşılan olmayan derlemelerden örnekler, nesneler, Thread iç içe dizeler ve uzaktan iletişim kullanarak uygulama etki alanları arasında paylaşılan bazı dizeler gibi Type çevik sınıflar kilitlendiğinde AppDomain bu durum oluşur. Bu kilitler artık işlem genelinde değildir. İşlem genelinde bir uygulama etki alanı kilidinin varlığını belirlemek için, kilit içindeki kodun disk üzerindeki bir dosya veya büyük olasılıkla bir veritabanı gibi dış, kalıcı bir kaynak kullanıp kullanmadığını belirleyin.
Korumalı kod bir dış kaynak kullanıyorsa bir AppDomain içinde kilit almanın sorunlara neden olabileceğini unutmayın çünkü bu kod birden çok uygulama etki alanı arasında aynı anda çalıştırılabilir. Bu, bir günlük dosyasına yazarken veya işlemin tamamı için bir yuvaya bağlanırken sorun olabilir. Bu değişiklikler, adlandırılmış Mutex veya Semaphore örnek kullanmak dışında işlem genel kilidi almak için yönetilen kodu kullanmanın kolay bir yolu olmadığı anlamına gelir. aynı anda iki uygulama etki alanında çalışmayan kod oluşturun veya veya Semaphore sınıflarını Mutex kullanın. Mevcut kod değiştirilemiyorsa, bu eşitlemeyi gerçekleştirmek için mutex adlı bir Win32 kullanmayın çünkü fiber modunda çalıştırmak, aynı işletim sistemi iş parçacığının bir mutex alıp serbest bırakacağını garanti edemeyeceğiniz anlamına gelir. Kod kilidini yönetilmeyen kod kullanarak eşitlemek yerine CLR'nin farkında olduğu şekilde eşitlemek için yönetilen Mutex sınıfı veya adlandırılmış ManualResetEventbir , AutoResetEventveya Semaphore a kullanmanız gerekir.
Lock(typeof(MyType)) kullanmaktan kaçının
Tüm uygulama etki alanlarında paylaşılan kodun yalnızca bir kopyasına sahip paylaşılan derlemelerdeki özel ve genel Type nesneler de sorun sunar. Paylaşılan derlemeler için işlem başına yalnızca bir Type örnek vardır ve bu da birden çok uygulama etki alanının aynı Type örneği paylaştığı anlamına gelir. Bir örneğe kilit Type almak, yalnızca AppDomainişlemini değil, tüm işlemi etkileyen bir kilit alır. AppDomain Bir nesne kilitlenirseType, bu iş parçacığı aniden durdurulur, kilidi serbest bırakmaz. Bu kilit daha sonra diğer uygulama etki alanlarının kilitlenmesine neden olabilir.
Statik yöntemlerde kilitleri almak için iyi bir yol, koda statik iç eşitleme nesnesi eklemeyi içerir. Bu, varsa sınıf oluşturucusunda başlatılabilir, ancak değilse şu şekilde başlatılabilir:
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;
}
}
Daha sonra kilitlendiğinde, kilitlemek InternalSyncObject
üzere bir nesne elde etmek için özelliğini kullanın. Sınıf oluşturucunuzda iç eşitleme nesnesini başlatmışsanız özelliğini kullanmanız gerekmez. Çift denetim kilidi başlatma kodu şu örnekteki gibi görünmelidir:
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;
}
}
Kilitle ilgili bir not(bu)
Genel olarak erişilebilen tek bir nesneye kilitlenmek genel olarak kabul edilebilir. Ancak, nesne bir alt sistemin tamamının kilitlenmesine neden olabilecek tek bir nesneyse, yukarıdaki tasarım desenini de kullanmayı göz önünde bulundurun. Örneğin, bir SecurityManager nesnedeki bir kilit, içindeki kilitlenmeye AppDomain neden olabilir ve bu da tüm AppDomain nesneyi kullanılamaz hale getirir. Bu türdeki genel olarak erişilebilir bir nesneye kilitlenmemek iyi bir uygulamadır. Ancak tek bir koleksiyon veya dizideki kilit genellikle bir sorun sunmamalıdır.
Kod analizi kuralı
Uygulama etki alanları arasında kullanılabilecek veya güçlü bir kimlik hissine sahip olmayan türlerde kilit oluşturmayın. , , , , PropertyInfo, String, ValueTypeThreadveya öğesinden türetilen herhangi bir Typenesne üzerinde çağırmayın EnterMarshalByRefObject. MethodInfo
GC'yi kaldırın. KeepAlive çağrıları
Var olan kodun önemli bir kısmı gerektiği zaman kullanmaz KeepAlive veya uygun olmadığında kullanır. öğesine dönüştürdükten SafeHandlesonra sınıfların sonlandırıcısı olmadığı ancak işletim sistemi tanıtıcılarını son haline getirmek için kullandıkları SafeHandle varsayılarak öğesini çağırması KeepAlivegerekmez. Çağrısı KeepAlive tutmanın performans maliyeti göz ardı edilebilir olsa da, çağrısının KeepAlive artık mevcut olmayabilecek bir yaşam sorununu çözmek için gerekli veya yeterli olduğu algısı kodun korunmasını daha zor hale getirir. Ancak, COM birlikte çalışabilir CLR çağrılabilen sarmalayıcıları (RCW' ler) KeepAlive kullanırken kod için hala gereklidir.
Kod analizi kuralı
öğesini kaldırın KeepAlive.
HostProtection Özniteliğini Kullanma
HostProtectionAttribute (HPA), konak koruma gereksinimlerini belirlemek için bildirim temelli güvenlik eylemlerinin kullanılmasını sağlayarak konağın tam olarak güvenilen kodun bile sql Server gibi ExitShow belirli konak için uygun olmayan belirli yöntemleri çağırmasını engellemesini sağlar.
HPA yalnızca ortak dil çalışma zamanını barındıran ve SQL Server gibi konak koruması uygulayan yönetilmeyen uygulamaları etkiler. Uygulandığında, güvenlik eylemi sınıfın veya yöntemin kullanıma sağladığı konak kaynaklarına göre bir bağlantı talebi oluşturulmasına neden olur. Kod bir istemci uygulamasında veya konak korumalı olmayan bir sunucuda çalıştırılıyorsa, "buharlaşır" özniteliği; algılanmaz ve bu nedenle uygulanmaz.
Önemli
Bu özniteliğin amacı, güvenlik davranışını değil konağa özgü programlama modeli yönergelerini zorunlu kılmaktır. Programlama modeli gereksinimlerine uyumluluğu denetlemek için bir bağlantı talebi kullanılsa da, HostProtectionAttribute bu bir güvenlik izni değildir.
Konağın programlama modeli gereksinimleri yoksa, bağlantı talepleri gerçekleşmez.
Bu öznitelik aşağıdakileri tanımlar:
Konak programlama modeline uymayan, ancak aksi takdirde zararsız olan yöntemler veya sınıflar.
Konak programlama modeline uymayan ve sunucu tarafından yönetilen kullanıcı kodunun istikrarsızlaştırılmasına neden olabilecek yöntemler veya sınıflar.
Konak programlama modeline uymayan ve sunucu işleminin kendisinde istikrarsızlığa yol açabilen yöntemler veya sınıflar.
Not
Konak korumalı bir ortamda yürütülebilecek uygulamalar tarafından çağrılacak bir sınıf kitaplığı oluşturuyorsanız, bu özniteliği kaynak kategorilerini kullanıma HostProtectionResource sunan üyelere uygulamanız gerekir. Bu özniteliğe sahip .NET Framework sınıf kitaplığı üyeleri yalnızca hemen çağıranın denetlenmasına neden olur. Kitaplık üyenizin de aynı şekilde hemen çağıranın denetimine neden olması gerekir.
Lütfen içinde HPA HostProtectionAttributehakkında daha fazla bilgi edinin.
Kod analizi kuralı
SQL Server için, eşitlemeyi veya iş parçacığını tanıtmak için kullanılan tüm yöntemlerin HPA ile tanımlanması gerekir. Bu, durumu paylaşan, eşitlenen veya dış işlemleri yöneten yöntemleri içerir. SQL Server'ı HostProtectionResource etkileyen değerler , Synchronizationve ExternalProcessMgmtşeklindedirSharedState. Ancak, yalnızca SQL'i etkileyen kaynakları kullananlar değil, herhangi bir yöntemi kullanıma sunan herhangi HostProtectionResource bir yöntem bir HPA tarafından tanımlanmalıdır.
Yönetilmeyen kodda süresiz olarak engellemeyin
YÖNETILEN kod yerine yönetilmeyen kodda engelleme, CLR iş parçacığını durduramadığından hizmet reddi saldırısına neden olabilir. Engellenen iş parçacığı, CLR'nin en azından bazı son derece güvenli olmayan işlemler yapmadan öğesini kaldırmasını AppDomainengeller. Windows eşitleme temel öğesini kullanarak engelleme, izin veremediğimiz bir şeyin açık bir örneğidir. Mümkünse bir yuvada çağrısının ReadFile
engellenmesinden kaçınılmalıdır; ideal olarak Windows API'sinin zaman aşımına uğradı gibi bir işlem için bir mekanizma sağlaması gerekir.
yerel olarak çağıran herhangi bir yöntem ideal olarak makul, sonlu bir zaman aşımı ile bir Win32 çağrısı kullanmalıdır. Kullanıcının zaman aşımını belirtmesine izin veriliyorsa, kullanıcının belirli bir güvenlik izni olmadan sonsuz bir zaman aşımı belirtmesine izin verilmemelidir. Kılavuz olarak, bir yöntem yaklaşık 10 saniyeden uzun süre engellenecekse, zaman aşımlarını destekleyen bir sürüm kullanıyor olmanız veya ek CLR desteğine ihtiyacınız vardır.
Sorunlu API'lere bazı örnekler aşağıda verilmiştir. Kanallar (hem anonim hem de adlandırılmış) zaman aşımı ile oluşturulabilir; ancak kodun hiçbir zaman çağırmadığından CreateNamedPipe
veya WaitNamedPipe
NMPWAIT_WAIT_FOREVER ile aramadığından emin olması gerekir. Ayrıca, zaman aşımı belirtilse bile beklenmeyen engellemeler olabilir. Anonim kanalda çağrılması WriteFile
, tüm baytlar yazılana kadar engellenir; başka bir deyişle arabellekte okunmamış veriler varsa, WriteFile
okuyucu kanalın arabelleğinde yer boşaltana kadar çağrı engellenir. Yuvalar her zaman zaman zaman aşımı mekanizmasını kabul eden bir API kullanmalıdır.
Kod analizi kuralı
Yönetilmeyen kodda zaman aşımı olmadan engelleme bir hizmet reddi saldırısıdır. , , WaitForSingleObjectEx
, WaitForMultipleObjects
MsgWaitForMultipleObjects
ve MsgWaitForMultipleObjectsEx
için WaitForSingleObject
platform çağırma çağrıları gerçekleştirmeyin. NMPWAIT_WAIT_FOREVER kullanmayın.
STA'ya Bağımlı özellikleri tanımlama
COM tek iş parçacıklı daireler (STA) kullanan tüm kodları belirleyin. STA'lar SQL Server işleminde devre dışı bırakılır. performans sayaçları veya pano gibi öğesine CoInitialize
bağlı özellikler SQL Server'da devre dışı bırakılmalıdır.
Sonlandırıcıların eşitleme sorunlarının bulunmadığından emin olun
.NET Framework'ün gelecek sürümlerinde birden çok sonlandırıcı iş parçacığı olabilir, yani aynı türün farklı örnekleri için sonlandırıcılar aynı anda çalıştırılır. Tamamen iş parçacığı güvenli olması gerekmez; çöp toplayıcı, belirli bir nesne örneği için sonlandırıcıyı yalnızca bir iş parçacığının çalıştıracağını garanti eder. Ancak, birden çok farklı nesne örneğinde aynı anda çalışırken yarış koşullarını ve kilitlenmeleri önlemek için sonlandırıcıların kodlanması gerekir. Günlük dosyasına yazma gibi herhangi bir dış durum kullanıldığında, sonlandırıcıda iş parçacığı oluşturma sorunları işlenmelidir. İş parçacığı güvenliği sağlamak için sonlandırmaya güvenmeyin. Sonlandırıcı iş parçacığında durumu depolamak için yönetilen veya yerel iş parçacığı yerel depolama kullanmayın.
Kod analizi kuralı
Sonlandırıcılar eşitleme sorunlarından arınmalıdır. Sonlandırıcıda statik bir değiştirilebilir durum kullanmayın.
Mümkünse yönetilmeyen bellekten kaçının
Yönetilmeyen bellek, işletim sistemi tutamacı gibi sızdırılabilir. Mümkünse stackalloc veya sabit deyim gibi sabitlenmiş yönetilen bir nesne veya GCHandle bayt kullanarak[] kullanarak yığındaki belleği kullanmayı deneyin. Sonunda GC bunları temizler. Ancak, yönetilmeyen bellek ayırmanız gerekiyorsa, bellek ayırmayı sarmak için öğesinden SafeHandle türetilen bir sınıf kullanmayı göz önünde bulundurun.
Yeterli olmayan en az bir durum SafeHandle olduğunu unutmayın. Bellek ayıran veya boşaltan COM yöntemi çağrıları için, bir DLL'nin belleği başka bir DLL ile CoTaskMemAlloc
CoTaskMemFree
boşaltması yaygın bir durumdur. SafeHandle Yönetilmeyen belleğin ömrünü diğer DLL'nin belleğin ömrünü SafeHandle denetlemesine izin vermek yerine, bu yerlerde kullanmak uygun olmayacaktır.
Catch'in tüm kullanımlarını gözden geçirme(Özel Durum)
Belirli bir özel durum yerine tüm özel durumları yakalayan catch blokları artık zaman uyumsuz özel durumları da yakalar. Atlanmış olabilecek önemli bir kaynak serbest bırakma veya backout kodu aramanın yanı sıra, bir , StackOverflowExceptionveya OutOfMemoryExceptionişlemek ThreadAbortExceptioniçin catch bloğunun kendi içinde hatalı olabilecek davranışları arayarak her catch(Özel Durum) bloğunu inceleyin. Bu kodun yalnızca belirli özel durumları görebileceğini veya bir özel durum oluştuğunda tam olarak tek bir nedenden dolayı başarısız olduğunu günlüğe kaydediyor veya bazı varsayımlarda bulunuyor olabileceğini unutmayın. Bu varsayımların içerecek ThreadAbortExceptionşekilde güncelleştirilmiş olması gerekebilir.
Dize biçimlendirme yöntemleri gibi, tüm özel durumları yakalayan tüm yerleri, oluşturulacağını beklediğiniz belirli bir FormatException özel durum türünü yakalayacak şekilde değiştirmeyi göz önünde bulundurun. Bu, catch bloğunun beklenmeyen özel durumlarda çalışmasını engeller ve kodun beklenmeyen özel durumlar yakalayarak hataları gizlememesini sağlamaya yardımcı olur. Genel bir kural olarak hiçbir zaman kitaplık kodundaki bir özel durumu işlemez (bir özel durumu yakalamanızı gerektiren kod, çağırdığınız kodda tasarım kusurunu gösterebilir). Bazı durumlarda bir özel durum yakalamak ve daha fazla veri sağlamak için farklı bir özel durum türü oluşturmak isteyebilirsiniz. Bu durumda iç içe özel durumları kullanın ve hatanın gerçek nedenini yeni özel durumun özelliğinde InnerException depolar.
Kod analizi kuralı
Yönetilen koddaki tüm nesneleri yakalayan veya tüm özel durumları yakalayan tüm yakalama bloklarını gözden geçirin. C# dilinde bu, hem hem catch(Exception)
{}de catch
{} bayraklama anlamına gelir. Özel durum türünü çok özel hale getirebilirsiniz veya beklenmeyen bir özel durum türü yakalarsa kötü bir şekilde davranmadığından emin olmak için kodu gözden geçirin.
Yönetilen iş parçacığının win32 iş parçacığı olduğunu varsaymayın – Fiber
Yönetilen iş parçacığı yerel depolamayı kullanmak işe yarayabilir, ancak yönetilmeyen iş parçacığı yerel depolama alanı kullanmayabilir veya kodun geçerli işletim sistemi iş parçacığında yeniden çalıştırılacağını varsayabilirsiniz. İş parçacığının yerel ayarı gibi ayarları değiştirmeyin. Bir kilit giren işletim sistemi iş parçacığını gerektirdiğinden veya platform çağrısı aracılığıyla çağırmayın InitializeCriticalSection
CreateMutex
, kilit de kilit çıkmak. Fiber kullanılırken bu durum söz konusu olmadığından Win32 kritik bölümleri ve muteksleri doğrudan SQL'de kullanılamaz. Yönetilen Mutex sınıfın bu iş parçacığı benzimliği sorunlarını işlemediğini unutmayın.
Yönetilen iş parçacığı yerel depolama alanı ve iş parçacığının geçerli kullanıcı arabirimi kültürü de dahil olmak üzere yönetilen bir Thread nesnedeki durumun çoğunu güvenle kullanabilirsiniz. Ayrıca, mevcut bir statik değişkenin değerini yalnızca geçerli yönetilen iş parçacığı tarafından erişilebilir hale getiren öğesini de kullanabilirsiniz ThreadStaticAttribute(bu, CLR'de fiber yerel depolama yapmanın başka bir yoludur). Programlama modeli nedenleriyle, SQL'de çalışırken iş parçacığının geçerli kültürünü değiştiremezsiniz.
Kod analizi kuralı
SQL Server fiber modunda çalışır; iş parçacığı yerel depolaması kullanmayın. , , TlsFree
TlsGetValue
ve platform çağrılarından TlsAlloc
kaçınınTlsSetValue.
SQL Server'ın kimliğe bürünme işlemlerini işlemesine izin ver
Kimliğe bürünme iş parçacığı düzeyinde çalıştığından ve SQL fiber modunda çalışabildiğinden, yönetilen kod kullanıcıların kimliğine bürünmemeli ve çağrılamamalıdır RevertToSelf
.
Kod analizi kuralı
Kimliğe bürünme işlemlerini SQL Server'ın işlemesine izin verin. , , ImpersonateAnonymousToken
, , DdeImpersonateClient
, ImpersonateDdeClientWindow
, , ImpersonateLoggedOnUser
, ImpersonateNamedPipeClient
, ImpersonateSelf
, RpcImpersonateClient
, RpcRevertToSelf
RpcRevertToSelfEx
veya SetThreadToken
kullanmayınRevertToSelf
.
İş Parçacığını çağırma::Askıya Al
Bir iş parçacığını askıya alma özelliği basit bir işlem gibi görünebilir, ancak kilitlenmelere neden olabilir. Kilit tutan bir iş parçacığı ikinci bir iş parçacığı tarafından askıya alınırsa ve ikinci iş parçacığı aynı kilidi almayı denerse, kilitlenme oluşur. Suspend şu anda güvenlik, sınıf yükleme, uzaktan iletişim ve yansımayı etkileyebilir.
Kod analizi kuralı
çağrısı Suspendyapma. Bunun yerine veya ManualResetEvent gibi Semaphore gerçek bir eşitleme temel öğesini kullanmayı göz önünde bulundurun.
Kısıtlanmış yürütme bölgeleri ve güvenilirlik sözleşmeleriyle kritik işlemleri koruma
Paylaşılan durumu güncelleştiren veya kesin olarak tamamen başarılı veya tamamen başarısız olması gereken karmaşık bir işlem gerçekleştirirken, bunun kısıtlanmış yürütme bölgesi (CER) tarafından korunduğundan emin olun. Bu, kodun her durumda, hatta ani bir iş parçacığı iptali veya ani AppDomain bir kaldırma işlemiyle çalışmasını garanti eder.
CER, çağrısının hemen önünde yer aldığı belirli try/finally
bir blokdur PrepareConstrainedRegions.
Bunun yapılması, tam zamanında derleyiciye bloğu çalıştırmadan önce finally bloğundaki tüm kodu hazırlamasını try
sağlar. Bu, finally bloğundaki kodun derlendiğini ve her durumda çalıştırılacağını garanti eder. Cer'de boş try
bir bloğun olması sık karşılaşılan bir durum değildir. CER kullanmak, zaman uyumsuz iş parçacığı iptallerine ve bellek dışı özel durumlara karşı koruma sağlar. Aşırı derin kod için yığın taşmalarını ek olarak işleyen bir CER biçimi için bkz ExecuteCodeWithGuaranteedCleanup .