को देखते हुए:ThreadLocks और स्टेटिक कंस्ट्रक्टर्स
एक ASP.net वेब एपीआई आवेदन IIS में की मेजबानी की। एप्लिकेशन प्लगइन के लिए प्रत्येक के बारे में 30 ऐप डोमेन बनाता है जो कुछ बाहरी काम करता है।
एप्लिकेशन बहुत सारे उपयोगकर्ताओं की सेवा करता है और अधिकतर समय बहुत अच्छी तरह से चलता है, लेकिन कुछ बार (दिन या यहां तक कि सप्ताहों के बाद) यह अचानक लटकता है।
समस्या:
एक WebApplication कभी कभी है "रुक जाता है" जो w3wp.exe को पुनः आरंभ करने की माँग का कारण।
इस स्थिति में डंप की कुछ परीक्षाओं के बाद हमने पाया कि इस क्षण में बहुत सारे धागे (कभी-कभी लगभग 15.000) होते हैं।
सामान्य स्थिति में हम कभी भी एक सौ धागे का निरीक्षण नहीं करते हैं।
DebugDiag कहते हैं एक धागा दूसरों
अब हमने देखा है कि धागा 44 (और कई कई अन्य लोगों, के बारे में 90%) में अवरुद्ध होता है, अंत में एक ही फोन है :
विधि ही किसी भी ताला या सूत्रण behavior.but यह अपने स्थिर निर्माता के विषय में एक असामान्य बात है नहीं है। ctor इस तरह दिखता है:
static TimeZoneHelper()
{
using (StringReader reader = new StringReader(Resources.TimeZones))
{
string line;
while ((line = reader.ReadLine()) != null)
{
string[] parts = line.Split(';');
TimeZoneInfo timeZone = TimeZoneInfo.FindSystemTimeZoneById(parts[1]);
timeZones[parts[0]] = timeZone;
}
}
}
इसके अलावा डिबग विश्लेषण दर्शाता है कि आवेदन एक सक्रिय जीसी में था (और आप संभावित पूछना होगा के रूप में: हम कभी भी स्वयं एक gc.collect प्रदर्शित नहीं)
प्रश्न क्या कोई सबूत बताता है कि इस प्रकार का कोड एक स्थिर ctor में समस्याग्रस्त है? भले ही कार्य या थ्रेडिंग कोड न हो? शायद जीसी प्रगति खुद से संबंधित कुछ मैं एक सार ctor inlcuding इस वर्ग के मुख्य तरीके से युक्त बनाया
TimeZoneHelper (के रूप में वस्तु डिस्पोजेबल, यहां तक कि एक निपटाने कोड नहीं होने तो क्या होगा?) है और विधि है जिसके TimeZoneHelper.ToTimeZoneOffset
बुलाया गया था: में
https://gist.github.com/Gentlehag/9d564555261da0e73366
मुख्य बात विधि परिणाम एक Dictionary.TryGet (ctor में बनाया गया था कौन सा)
है 0संपादित करें बीटीडब्ल्यू मैं प्रत्येक एपडोमेन में भी जोड़ना चाहता हूं, एक असेंबली समाधान घटना बाध्य है। कोड यहाँ देखा जा सकता:
https://gist.github.com/Gentlehag/4726b6d888adb149684d
महत्वपूर्ण अपडेट मैं एक सहयोगी हूँ और अभी कुछ और जानकारी जोड़ना चाहते हैं। हमें एक और परिदृश्य भी मिला जो बहुत समान है। मैं धागा कि ब्लॉक का मालिक से स्टैकट्रेस है:
000000c898897560 00007ff8855b7e5d System.Collections.Generic.Dictionary`2[[System.__Canon, mscorlib],[System.__Canon, mscorlib]].FindEntry(System.__Canon)
000000c8988975d0 00007ff8855b7d34 System.Collections.Generic.Dictionary`2[[System.__Canon, mscorlib],[System.__Canon, mscorlib]].TryGetValue(System.__Canon, System.__Canon ByRef)
000000c898897610 00007ff88f6152b3 GP.Components.Extensions.AppDomains.RemotingRunner.CurrentDomain_AssemblyResolve(System.Object, System.ResolveEventArgs)
000000c8988978a0 00007ff886f7276c System.AppDomain.OnAssemblyResolveEvent(System.Reflection.RuntimeAssembly, System.String)
000000c898897bd0 00007ff8e4b2a7f3 [GCFrame: 000000c898897bd0]
000000c898899b78 00007ff8e4b2a7f3 [HelperMethodFrame_PROTECTOBJ: 000000c898899b78] System.Reflection.RuntimeAssembly._nLoad(System.Reflection.AssemblyName, System.String, System.Security.Policy.Evidence, System.Reflection.RuntimeAssembly, System.Threading.StackCrawlMark ByRef, IntPtr, Boolean, Boolean, Boolean)
000000c898899c80 00007ff886f7224e System.Reflection.RuntimeAssembly.InternalGetSatelliteAssembly(System.String, System.Globalization.CultureInfo, System.Version, Boolean, System.Threading.StackCrawlMark ByRef)
000000c898899d60 00007ff886f716c8 System.Resources.ManifestBasedResourceGroveler.GetSatelliteAssembly(System.Globalization.CultureInfo, System.Threading.StackCrawlMark ByRef)
000000c898899df0 00007ff885b932fb System.Resources.ManifestBasedResourceGroveler.GrovelForResourceSet(System.Globalization.CultureInfo, System.Collections.Generic.Dictionary`2, Boolean, Boolean, System.Threading.StackCrawlMark ByRef)
000000c898899eb0 00007ff885b92ecb System.Resources.ResourceManager.InternalGetResourceSet(System.Globalization.CultureInfo, Boolean, Boolean, System.Threading.StackCrawlMark ByRef)
000000c898899fa0 00007ff885b92b73 System.Resources.ResourceManager.InternalGetResourceSet(System.Globalization.CultureInfo, Boolean, Boolean)
000000c898899ff0 00007ff885b92014 System.Resources.ResourceManager.GetString(System.String, System.Globalization.CultureInfo)
000000c89889a0a0 00007ff89914aa62 NewRelic.Agent.Core.Config.ConfigurationLoader.InitializeFromXml(System.String, System.String)
000000c89889a140 00007ff89914a838 NewRelic.Agent.Core.Config.ConfigurationLoader.Initialize(System.String)
000000c89889a1a0 00007ff899143be9 NewRelic.Agent.Core.Config.ConfigurationLoader.Initialize()
000000c89889a210 00007ff899123a27 NewRelic.Agent.Core.Agent+AgentSingleton.CreateInstance()
000000c89889a280 00007ff8991239c2 NewRelic.Agent.Core.Singleton`1[[System.__Canon, mscorlib]]..ctor(System.__Canon)
000000c89889a2c0 00007ff89912388b NewRelic.Agent.Core.Agent..cctor()
000000c89889a700 00007ff8e4b2a7f3 [GCFrame: 000000c89889a700]
000000c89889ce88 00007ff8e4b2a7f3 [PrestubMethodFrame: 000000c89889ce88] NewRelic.Agent.Core.Agent.get_Instance()
000000c89889cef0 00007ff89912358c NewRelic.Agent.Core.AgentShim.GetTracer(System.String, UInt32, System.String, System.String, System.Type, System.String, System.String, System.String, System.Object, System.Object[])
000000c89889d280 00007ff8e4b2a7f3 [DebuggerU2MCatchHandlerFrame: 000000c89889d280]
यह TimeZoneHelper वर्ग के बारे में नहीं है, लेकिन यह दिलचस्प एक आम पहलू है कि वहाँ है: दोनों वर्ग भार उनके स्थिर निर्माता में एक संसाधन (या तो न्यूज़ेलिक या टाइमज़ोन के साथ फ़ाइल के लिए कॉन्फ़िगरेशन फ़ाइल)। तो परिदृश्य प्रतीत हो रहा है निम्नलिखित:
- एकाधिक धागे वर्ग
- पहले धागा स्थिर निर्माता के लिए ताला हो जाता है का उपयोग करने के लिए प्रयास करें और इस निर्माता
- एक संसाधन भरी हुई है और नेट चलाता है रनटाइम संसाधन असेंबली लोड करने का प्रयास करता है।
- हम संसाधन असेंबली लोड करने और किसी तरह से डेडलॉक का कारण बनने के लिए असेंबली रिसोलव-इवेंट को पकड़ते हैं, सवाल यह है कि कैसे?
भले ही विधि में कोई लॉकिंग या थ्रेडिंग न हो, जैसा कि आप कहते हैं, कृपया इसे अभी भी पोस्ट करें। यह एक ढांचा विधि को कॉल कर रहा है जो कवर के तहत लॉक का उपयोग करता है। आम तौर पर, यदि स्टैक निशान आपको बताते हैं कि एक विशेष विधि अवरुद्ध हो रही है, तो यह मानना सुरक्षित है कि वह विधि * वास्तव में अवरुद्ध है *। (स्थैतिक कन्स्ट्रक्टर अपने नाम ('.cctor') के साथ एक अलग विधि है।) इसके अलावा, संपूर्ण स्टैक ट्रेस केवल अंतिम फ्रेम की तुलना में अधिक उपयोगी है। –
मैंने कोड –
कोड के साथ एक ग्रिस्ट को जोड़ा - मेरा बुरा - मुझे इस तथ्य को याद आया कि कॉल विधि निकाय से नहीं है बल्कि 'प्रेस्ट्यूब मोडरफ्रेम' है, जो सीएलआर आंतरिक लॉक को शामिल करने का सुझाव देता है। अधिक प्रासंगिक जानकारी जो आप जोड़ सकते हैं: अप्रबंधित कॉल स्टैक (जैसा कि 'केबी' के साथ लौटाया गया है), और विशेष रूप से ताला के मालिक के धागे (ऊपर दिए गए उदाहरण में 44)। यदि कॉल स्टैक * लॉक के मालिक के धागे में से एक है (मुझे यकीन नहीं है कि "44" यहां थ्रेड आईडी है), तो आपको यह पता लगाना होगा कि वह थ्रेड वास्तव में क्या इंतजार कर रहा है (कौन सा हैंडल पास हो गया है 'ZwWaitForSingleObject')। स्टैक ट्रेस वहां मदद करनी चाहिए। –