вторник, 27 июля 2010 г.

Простой пример зависшего на shutdown-е приложения

   Небольшой тестовый пример, демонстрирующий методику поиска причины завичания приложения при завершении работы системы [1].

   Практическая часть, так сказать :)


   Тестовый пример был выполнен на машине под управлением Windows XP SP3 Professional. Для создания интересующей нас ситуации запускаем блокнот, вводим какой-то текст и выключаем компьютер. Блокнот при этом покажет MessageBox с вопросом, мол сохранить изменения или ну его? Ничего не делаем - просто ждем, а через некоторое время система покажет окно


   Для начала открываем дамп csrss.exe и находим поток, который отвечает за завершение процессов интерактивного пользователя:
0:000> ~* k

.  0  Id: 33c.344 Suspend: 0 Teb: 7ffdc000 Unfrozen
ChildEBP RetAddr  
004afe94 7c90daea ntdll!KiFastSystemCallRet
004afe98 75b37eae ntdll!ZwRequestWaitReplyPort+0xc
004afff4 00000000 winsrv!TerminalServerRequestThread+0x228

...

   7  Id: 33c.394 Suspend: 0 Teb: 7ffd6000 Unfrozen
ChildEBP RetAddr  
00bbfbbc 7c90df4a ntdll!KiFastSystemCallRet
00bbfbc0 7c809590 ntdll!ZwWaitForMultipleObjects+0xc
00bbfc5c 7e3695f9 kernel32!WaitForMultipleObjectsEx+0x12c
00bbfcb8 7e3696a8 user32!RealMsgWaitForMultipleObjectsEx+0x13e
00bbfcd4 75b48af9 user32!MsgWaitForMultipleObjects+0x1f
00bbfdcc 75b49184 winsrv!ThreadShutdownNotify+0x1a6
00bbfe28 75b16266 winsrv!UserClientShutdown+0x200
00bbfe78 75b48805 csrsrv!CsrShutdownProcesses+0xa1
00bbfeb8 75b48938 winsrv!_ExitWindowsEx+0x100
00bbfed0 75b14a47 winsrv!SrvExitWindowsEx+0x28
00bbfff4 00000000 csrsrv!CsrApiRequestThread+0x431

   8  Id: 33c.398 Suspend: 0 Teb: 7ffd5000 Unfrozen
ChildEBP RetAddr  
00c0ffe0 75b3ba1a ntdll!KiFastSystemCallRet
00000000 f000ff53 winsrv!NtUserCallOneParam+0xc
WARNING: Frame IP not in any known module. Following frames may be wrong.
00000000 00000000 0xf000ff53

   9  Id: 33c.238 Suspend: 0 Teb: 7ffd4000 Unfrozen
ChildEBP RetAddr  
010df708 7c90df5a ntdll!KiFastSystemCallRet
010df70c 7c8025db ntdll!ZwWaitForSingleObject+0xc
010df770 7c802542 kernel32!WaitForSingleObjectEx+0xa8
010df784 7c831610 kernel32!WaitForSingleObject+0x12
010df798 75b38045 kernel32!GetOverlappedResult+0x30
010dfff4 00000000 winsrv!Win32CommandChannelThread+0x71
   Рассмотрим стек этого потока более подробно:
0:007> kb
ChildEBP RetAddr  Args to Child              
00bbfbbc 7c90df4a 7c809590 00000003 00bbfbe8 ntdll!KiFastSystemCallRet
00bbfbc0 7c809590 00000003 00bbfbe8 00000001 ntdll!ZwWaitForMultipleObjects+0xc
00bbfc5c 7e3695f9 00000003 00bbfc84 00000000 kernel32!WaitForMultipleObjectsEx+0x12c
00bbfcb8 7e3696a8 00000002 00bbfda4 ffffffff user32!RealMsgWaitForMultipleObjectsEx+0x13e
00bbfcd4 75b48af9 00000002 00bbfda4 00000000 user32!MsgWaitForMultipleObjects+0x1f
00bbfdcc 75b49184 8000000b 001503a8 00000000 winsrv!ThreadShutdownNotify+0x1a6
00bbfe28 75b16266 0017e5d8 00000200 75b15001 winsrv!UserClientShutdown+0x200
00bbfe78 75b48805 00bbfeac 00000200 00bbfeec csrsrv!CsrShutdownProcesses+0xa1
00bbfeb8 75b48938 00164838 00000200 00164838 winsrv!_ExitWindowsEx+0x100
00bbfed0 75b14a47 00bbfeec 00bbffd8 00000005 winsrv!SrvExitWindowsEx+0x28
00bbfff4 00000000 00000000 000000c8 000001f7 csrsrv!CsrApiRequestThread+0x431
   По адресу 0x00bbfda4 находится массив, содержащий 2 описателя, которые были переданы в функцию MsgWaitForMultipleObjects. Первый представляет собой описатель события отмены зачершения работы, а второй - описатель интересующего нас потока:
0:007> dp 00bbfda4 l2
00bbfda4  0000003c 00000564

0:007> !handle 0000003c 
Handle 0000003c
  Type          Event
  
0:007> !handle 00000564
Handle 00000564
  Type          Thread
   Осталось только определить ClientID этого потока:
0:007> !handle 00000564 f
Handle 00000564
  Type          Thread
  Attributes    0
  GrantedAccess 0x1f03ff:
         Delete,ReadControl,WriteDac,WriteOwner,Synch
         Terminate,Suspend,Alert,GetContext,SetContext,SetInfo,QueryInfo,SetToken,Impersonate,DirectImpersonate
  HandleCount   2
  PointerCount  6
  Name          
  Object specific information
    Thread Id   26c.4ac
    Priority    10
    Base Priority 0

   Переходим ко второй части марлезонского балета - изучению оставшегося дампа. Для начала просто убеждаемся, что проблемный поток действительно принадлежит проблемному приложению (блокноту).
0:000> ~*
.  0  Id: 26c.4ac Suspend: 0 Teb: 7ffde000 Unfrozen
      Start: notepad!WinMainCRTStartup (0100739d) 
      Priority: 0  Priority class: 32  Affinity: 3
   И изучаем его стек:
0:000> kb
ChildEBP RetAddr  Args to Child              
0006f3f8 7e369418 7e37770a 001503a8 00000000 ntdll!KiFastSystemCallRet
0006f430 7e3749c4 000f028c 001503a8 00000001 user32!NtUserWaitMessage+0xc
0006f458 7e38a956 7e360000 0009dde0 001503a8 user32!InternalDialogBox+0xd0
0006f718 7e38a2bc 0006f874 0000000a 0009ec38 user32!SoftModalMessageBox+0x938
0006f868 7e3b63fd 0006f874 00000028 001503a8 user32!MessageBoxWorker+0x2ba
0006f8c0 7e3a0853 001503a8 0009ec38 00095694 user32!MessageBoxTimeoutW+0x7a
0006f8e0 7e3b6579 001503a8 0009ec38 00095694 user32!MessageBoxExW+0x1b
0006f8fc 01001fc4 001503a8 0009ec38 00095694 user32!MessageBoxW+0x45
0006f91c 010027c7 001503a8 00095694 0009547a notepad!AlertBox+0x54
0006fb54 01003587 00000001 0006fbd8 01003429 notepad!CheckSave+0xb8
0006fb70 7e368734 001503a8 00000011 00000000 notepad!NPWndProc+0x15e
0006fb9c 7e368816 01003429 001503a8 00000011 user32!InternalCallWinProc+0x28
0006fc04 7e378ea0 00000000 01003429 001503a8 user32!UserCallWinProcCheckWow+0x150
0006fc58 7e378eec 004b23f8 00000011 00000000 user32!DispatchClientMessage+0xa3
0006fc80 7c90e473 0006fc90 00000018 004b23f8 user32!__fnDWORD+0x24
0006fca4 7e3694be 7e378e0d 001503a8 0000003b ntdll!KiUserCallbackDispatcher+0x13
0006fcf8 7e378dd9 001503a8 0000003b 8000000b user32!NtUserMessageCall+0xc
0006fd14 7e378d77 001503a8 0000003b 8000000b user32!RealDefWindowProcW+0x47
0006fd5c 010037dc 001503a8 0000003b 8000000b user32!DefWindowProcW+0x72
0006fd84 7e368734 001503a8 0000003b 8000000b notepad!NPWndProc+0x3b3
0006fdb0 7e368816 01003429 001503a8 0000003b user32!InternalCallWinProc+0x28
0006fe18 7e378ea0 00000000 01003429 001503a8 user32!UserCallWinProcCheckWow+0x150
0006fe6c 7e378eec 004b23f8 0000003b 8000000b user32!DispatchClientMessage+0xa3
0006fe94 7c90e473 0006fea4 00000018 004b23f8 user32!__fnDWORD+0x24
0006feb8 7e3691be 7e3691f1 0006fefc 00000000 ntdll!KiUserCallbackDispatcher+0x13
0006fed8 01002a1b 0006fefc 00000000 00000000 user32!NtUserGetMessage+0xc
0006ff1c 01007511 01000000 00000000 00092332 notepad!WinMain+0xe5
0006ffc0 7c817077 00efd470 7c90d96e 7ffdf000 notepad!WinMainCRTStartup+0x174
0006fff0 00000000 0100739d 00000000 78746341 kernel32!BaseProcessStart+0x23
   В нем видно, что поток отображает MessageBox и не может ответить на сообщение WM_QUERYENDSESSION/WM_ENDSESSION до тех пор, пока пользователь не закроет этот диалог:
0:000> du /c 100 0009ec38 
0009ec38  "Текст в файле Безымянный был изменен...Сохранить изменения?"

Ссылки
[1] Методика диагностики зависания приложения при shutduwn-е

1 комментарий:

  1. The best way to get free chips from slot machines - DrmCAD
    slot machines in your room with free spins and no deposit required, or 광주광역 출장샵 start earning chips from slots machines. slot machines 광명 출장마사지 in 창원 출장안마 the 울산광역 출장마사지 casino 청주 출장안마 with no deposit required

    ОтветитьУдалить