У меня проблемы с зависанием regsvr32.exe во время установки.DLL, назовем ее common.dll, регистрируется как часть процесса установки с использованием regsvr32.exe.Common.dll использует другую DLL, utility.dll.
Часть utility.dll содержит функции ведения журнала.Эта функция ведения журнала использует статический объект «Таймер» для периодической проверки размеров файла журнала и соответствующего разделения.Объект Timer включает свой собственный поток, который он использует для запуска таймера.Объект таймера внутри регистратора является статическим, поэтому он используется в нескольких экземплярах регистратора, которые используют статические потоки для указания на один и тот же файл.
Таймер имеет два события, таймер (созданный с помощью CreateWaitableTimer ())и стандартное событие синхронизации (CreateEvent ()) для запуска отключения потока.Поток запускается в конструкторе (_beginthreadex ()).Внутри функции потока есть ожидание вызова WaitForMultipleObjects () как по таймеру, так и по событию завершения работы.Wait ... () имеет значение INFINITE, и функция потока возвращается, когда установлено событие выключения (SetEvent ()).
(Выше приведено в качестве фона, ни одна его часть не может быть изменена как частьрешения и все DLL-файлы, регистратор и таймер работают правильно).
Проблема возникает во время работы regsvr32.exe.Он загружает файл common.dll, который загружает файл utility.dll, который инициализирует объект потока статического таймера.Поток запускается правильно, и он достигает вызова WaitForMultipleObjects () внутри функции потока.Как только регистрация завершается (почти мгновенно), вызывается деструктор таймера.Деструктор вызывает SetEvent () для события shutdown, , но WaitForMultipleObjects () никогда не возвращается. В качестве части попытки выяснить эту проблему я поставил вызов WaitForSingleObject () сразу после вызова SetEvent (),ожидание события отключенияЭто также никогда не возвращается, что приводит меня к мысли, что есть проблема с самим событием.У меня были следующие возможные объяснения:
- Проблема синхронизации.Процесс регистрации заканчивается очень быстро, и, возможно, поток переходит в состояние, в котором он не готов к закрытию?Тем не менее поток достигает вызова WaitForMultipleObjects (), что заставляет меня поверить, что это не проблема.
- Utility.dll выгружается программой regsvr32.exe.Я не совсем понимаю, как все это работает, но с помощью ProcessExplorer похоже, что regsvr32.exe все еще загружает dll, пока он висит, поэтому я не думаю, что это проблема.
- Тесныйцикл внутри regsvr32.exe во время выключения.Если процесс уничтожения для regsvr32.exe происходит в тесном цикле (то есть, в то время как (NotShutdown ()) и т. Д.), Возможно, это не уменьшает время процессора для потока таймера, что объясняет зависание.
Есть еще мысли по этому поводу?Я искал в интернете и не могу найти ничего, что удаленно связано с этой проблемой.
PS Я знаю, что решение проблемы заключается в использовании статического указателя и инициализации таймера, когда это действительно необходимои это решение, с которым я собираюсь.Однако я все еще хотел бы понять , почему это происходит, поскольку мне кажется совершенно нелепым, что SetEvent () не будет работать.
Вывод команды windbg! Locks:
0:000> !locks
CritSec ntdll!LdrpLoaderLock+0 at 7c97e178
LockCount 2
RecursionCount 1
OwningThread d8
EntryCount 4
ContentionCount 4
*** Locked
Scanned 253 critical sections
0:000> ~*kv
. 0 Id: a40.d8 Suspend: 0 Teb: 7ffdf000 Unfrozen
ChildEBP RetAddr Args to Child
0007e5ec 7c90df5a 7c8025db 00000764 00000000 ntdll!KiFastSystemCallRet (FPO: [0,0,0])
0007e5f0 7c8025db 00000764 00000000 00000000 ntdll!ZwWaitForSingleObject+0xc (FPO: [3,0,0])
0007e654 7c802542 00000764 ffffffff 00000000 kernel32!WaitForSingleObjectEx+0xa8 (FPO: [Non-Fpo])
*** WARNING: Unable to verify checksum for Utilityd.dll
0007e668 00a84e37 00000764 ffffffff 0007e71c kernel32!WaitForSingleObject+0x12 (FPO: [Non-Fpo])
0007e6c8 00a2e5af 0007e798 0007e754 00aa02e0 Utilityd!CThreadTimer::~CThreadTimer+0x97 [C:\xxx\ThreadTimer.cpp @ 49]
0007e71c 00aa02ae 00fe7a18 0007e740 00aa039b Utilityd!$E177+0x3f
0007e728 00aa039b 00a10000 00000000 00000000 Utilityd!_CRT_INIT+0xde [crtdll.c @ 236]
0007e740 7c90118a 00a10000 00000000 00000000 Utilityd!_DllMainCRTStartup+0xbb [crtdll.c @ 289]
0007e760 7c91e044 00aa02e0 00a10000 00000000 ntdll!LdrpCallInitRoutine+0x14
0007e858 7c80ac97 00950000 00000000 0003415e ntdll!LdrUnloadDll+0x41c (FPO: [Non-Fpo])
0007e86c 0100214e 00950000 00000000 00020bca kernel32!FreeLibrary+0x3f (FPO: [Non-Fpo])
0007ff1c 010024bf 01000000 00000000 00020bca regsvr32!wWinMain+0xad1 (FPO: [Non-Fpo])
0007ffc0 7c817077 00000018 00000000 7ffd4000 regsvr32!wWinMainCRTStartup+0x198 (FPO: [Non-Fpo])
0007fff0 00000000 01002327 00000000 78746341 kernel32!BaseProcessStart+0x23 (FPO: [Non-Fpo])
1 Id: a40.e98 Suspend: 0 Teb: 7ffde000 Unfrozen
ChildEBP RetAddr Args to Child
0104fe34 7c90df5a 7c91b24b 00000760 00000000 ntdll!KiFastSystemCallRet (FPO: [0,0,0])
0104fe38 7c91b24b 00000760 00000000 00000000 ntdll!ZwWaitForSingleObject+0xc (FPO: [3,0,0])
0104fec0 7c901046 0197e178 7c913978 7c97e178 ntdll!RtlpWaitForCriticalSection+0x132 (FPO: [Non-Fpo])
0104fec8 7c913978 7c97e178 00000000 7ffde000 ntdll!RtlEnterCriticalSection+0x46 (FPO: [1,0,0])
0104ff34 7c80c136 006e0065 00560074 00fe43d8 ntdll!LdrShutdownThread+0x22 (FPO: [Non-Fpo])
*** ERROR: Symbol file could not be found. Defaulted to export symbols for MSVCRTD.DLL -
0104ff6c 1020c061 00000000 00fe43d8 0104ffb4 kernel32!ExitThread+0x3e (FPO: [Non-Fpo])
WARNING: Stack unwind information not available. Following frames may be wrong.
0104ff7c 1020bfd8 00000000 006e0065 00560074 MSVCRTD!endthreadex+0x41
0104ffb4 7c80b729 00fe43d8 006e0065 00560074 MSVCRTD!beginthreadex+0x178
0104ffec 00000000 1020bf20 00fe43d8 00000000 kernel32!BaseThreadStart+0x37 (FPO: [Non-Fpo])
2 Id: a40.1708 Suspend: 0 Teb: 7ffdd000 Unfrozen
ChildEBP RetAddr Args to Child
0136fc0c 7c90df5a 7c91b24b 00000760 00000000 ntdll!KiFastSystemCallRet (FPO: [0,0,0])
0136fc10 7c91b24b 00000760 00000000 00000000 ntdll!ZwWaitForSingleObject+0xc (FPO: [3,0,0])
0136fc98 7c901046 0197e178 7c91e3b5 7c97e178 ntdll!RtlpWaitForCriticalSection+0x132 (FPO: [Non-Fpo])
0136fca0 7c91e3b5 7c97e178 0136fd2c 00000004 ntdll!RtlEnterCriticalSection+0x46 (FPO: [1,0,0])
0136fd18 7c90e457 0136fd2c 7c900000 00000000 ntdll!_LdrpInitialize+0xf0 (FPO: [Non-Fpo])
00000000 00000000 00000000 00000000 00000000 ntdll!KiUserApcDispatcher+0x7