Отладка после смерти с помощью WinDBG
У меня есть WCF-сервис, работающий на сервере, и иногда (1-2 раза в месяц) он вызывает COMException с информативным сообщением "Неизвестная ошибка (0x8005008)". Когда я погуглил для этой конкретной ошибки, я только получил темы о проблемах при создании виртуальных каталогов в IIS. И исходный код не имеет ничего общего с созданием виртуального каталога в IIS.
DirectoryServiceLib.LdapProvider.Directory - CreatePost - Could not create employee for 195001010000,000000000000: System.Runtime.InteropServices.COMException (0x80005008): Unknown error (0x80005008) at System.DirectoryServices.PropertyValueCollection.PopulateList
Я взял дамп памяти, когда ловил исключение для дальнейшего анализа в WinDBG. После переключения на нужный поток я выполнил команду!CLRStack:
000000001b8ab6d8 000000007708671a [NDirectMethodFrameStandalone: 000000001b8ab6d8] Common.MemoryDump.MiniDumpWriteDump(IntPtr, Int32, IntPtr, MINIDUMP_TYPE, IntPtr, IntPtr, IntPtr)
000000001b8ab680 000007ff002808d8 DomainBoundILStubClass.IL_STUB_PInvoke(IntPtr, Int32, IntPtr, MINIDUMP_TYPE, IntPtr, IntPtr, IntPtr)
000000001b8ab780 000007ff00280812 Common.MemoryDump.CreateMiniDump(System.String)
000000001b8ab7e0 000007ff0027b218 DirectoryServiceLib.LdapProvider.Directory.CreatePost(System.String, DirectoryServiceLib.Model.Post, DirectoryServiceLib.Model.Presumptions, Services.Common.SourceEnum, System.String)
000000001b8ad6d8 000007fef8816869 [HelperMethodFrame: 000000001b8ad6d8]
000000001b8ad820 000007feec2b6c6f System.DirectoryServices.PropertyValueCollection.PopulateList()
000000001b8ad860 000007feec225f0f System.DirectoryServices.PropertyValueCollection..ctor(System.DirectoryServices.DirectoryEntry, System.String)
000000001b8ad8a0 000007feec22d023 System.DirectoryServices.PropertyCollection.get_Item(System.String)
000000001b8ad8f0 000007ff00274d34 Common.DirectoryEntryExtension.GetStringAttribute(System.String)
000000001b8ad940 000007ff0027f507 DirectoryServiceLib.LdapProvider.DirectoryPost.Copy(DirectoryServiceLib.LdapProvider.DirectoryPost)
000000001b8ad980 000007ff0027a7cf DirectoryServiceLib.LdapProvider.Directory.CreatePost(System.String, DirectoryServiceLib.Model.Post, DirectoryServiceLib.Model.Presumptions, Services.Common.SourceEnum, System.String)
000000001b8adbe0 000007ff00279532 DirectoryServiceLib.WCFDirectory.CreatePost(System.String, DirectoryServiceLib.Model.Post, DirectoryServiceLib.Model.Presumptions, Services.Common.SourceEnum, System.String)
000000001b8adc60 000007ff001f47bd DynamicClass.SyncInvokeCreatePost(System.Object, System.Object[], System.Object[])
Мой вывод заключается в том, что он не работает, когда код вызывает System.DirectoryServices.PropertyCollection.get_Item(System.String).
Поэтому после выдачи!CLRStack -a я получаю такой результат:
000000001b8ad8a0 000007feec22d023 System.DirectoryServices.PropertyCollection.get_Item(System.String)
PARAMETERS:
this = <no data>
propertyName = <no data>
LOCALS:
<CLR reg> = 0x0000000001dcef78
<no data>
Мой самый первый вопрос: почему он не отображает данные об имени свойства? Я новичок в Windbg. Однако я выполнил дампобъект на = 0x0000000001dcef78:
0:013> !do 0x0000000001dcef78
Name: System.String
MethodTable: 000007fef66d6960
EEClass: 000007fef625eec8
Size: 74(0x4a) bytes
File: C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
String: personalprescriptioncode
Fields:
MT Field Offset Type VT Attr Value Name
000007fef66dc848 40000ed 8 System.Int32 1 instance 24 m_stringLength
000007fef66db388 40000ee c System.Char 1 instance 70 m_firstChar
000007fef66d6960 40000ef 10 System.String 0 shared static Empty
>> Domain:Value 0000000000174e10:00000000019d1420 000000001a886f50:00000000019d1420 <<
Поэтому, когда исходный код хочет получить персональный код прописки из Active Directory(что используется для постоянного уровня), происходит сбой. Оглядываясь назад на стек, это происходит при выдаче метода Copy. DirectoryServiceLib.LdapProvider.DirectoryPost.Copy (DirectoryServiceLib.LdapProvider.DirectoryPost)
Итак, глядя в исходный код:
DirectoryPost postInLimbo = DirectoryPostFactory.Instance().GetDirectoryPost(LdapConfigReader.Instance().GetConfigValue("LimboDN"), idGenPerson.ID.UserId);
if (postInLimbo != null)
newPost.Copy(postInLimbo);
Этот код ищет другой пост в OU=limbo с тем же UserId и, если он находит его, копирует атрибуты в новый пост. В этом случае это происходит, и происходит сбой с персональным кодом. Я посмотрел в Active Directory под OU=Limbo и там существует пост с атрибутом personalprescriptioncode=31243.
Вопрос 1: Почему он не отображает данные для некоторых ПАРАМЕТРОВ и МЕСТНЫХ? Это GC, который очистил до того, как был создан дамп памяти.
Вопрос 2: Могу ли я что-нибудь сделать, чтобы найти решение этой проблемы?
1 ответ
//
// MessageId: E_ADS_BAD_PARAMETER
//
// MessageText:
//
// One or more input parameters are invalid
//
#define E_ADS_BAD_PARAMETER _HRESULT_TYPEDEF_(0x80005008L)
Вы не можете видеть значения аргумента / локальной переменной, потому что код оптимизирован. Они хранятся в регистрах ЦП во время вызова, а не в стеке. Вы не можете найти иглу в стоге сена больше.