Outpost периодически намертво вешает систему

Тема в разделе "WASM.BEGINNERS", создана пользователем l_inc, 30 май 2011.

  1. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Booster
    Во-первых, откуда стало известно, что нет других мест в коде, где захватываются эти же спинлоки? Они гарантированно есть даже в пределах этой же функции, но выглядят безобидно.
    Во-вторых, именно потому что IRQL равен DISPATCH, как раз и происходит мёртвое зависание системы: два ядра, два активных потока в бесконечных циклах, причём оба на dispatch level.
    Конкретно этот системный код с багом вполне может и почти ни у кого не вызываться. А даже если и вызывается, то баг может проявляться достаточно редко.
    Такая частота появления отлично объясняется подряд идущими захватом и освобождением двух разных спинлоков и вытекающим из этого race condition. Стоило потоку успеть освободить g_rlConnTableLock, как deadlock'а бы не было.
    Ну то, что кто-то накосячил, — очевидный факт. Но этим кем-то вполне может быть и сама MS.
     
  2. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Я имел ввиду немного не то, функция захвата спинлока KeAcquireSpinLock - одна. И в ней то и происходит установка IRQL до DISPATCH, на многоядерных системах конечно этого не достаточно, но как-то решают эту проблему. Я к тому, что здесь проблема маловероятна, так как код этой функции наверняка вылизан. Проблема может быть в том, что кто-то взял спинлок, а освободить забыл. Но как мы поняли, ndis драйвер это сделать вполне может. Но драйвер-то чей? Оутпоста.

    Может и так, но определённо сказать невозможно. Я больше склоняюсь в сторону кривого драйвера стенки. У MS всё-таки тестирование получше.

    З.Ы. Ладно если хочешь, то думай что оутпост здесь не причём. ^)
     
  3. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Booster
    Известно, как: с помощью спинлока. На однопроцессорных системах только повышение до dispatch и спинлоком-то назвать нельзя, хоть функция и называется так же.
    Какой? KeAcquireSpinLock и аналогов? Разумеется, в них нет ошибок. Я говорю, что ошибки могут быть в wanarp.sys. В частности в WanNdisReceivePackets, т.к. она явно работает с несколькими одновременно захваченными спинлоками. Если порядок захвата не одинаков во всей системе, то deadlock — вполне ожидаемый результат.
    Я не думаю, что Outpost не причём. Я думаю, что он — не единственный подозреваемый.
     
  4. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Не совсем, повышение до dispatch это не спинлок. Спинлок это просто переменная, вокруг которой крутиться поток ожидая её освобождения и крутится он не на уровне dispatch. dispatch уровень нужен только для для установки/снятия состояния переменной(чтобы другой поток случайно дров не наломал) и устанавливается этот уровень кратковременно. Кстати вопрос, как ты вручную снял спинлок, если система полностью остановилась?
     
  5. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Ну это уже детский сад. Это всё неверно. Установка/снятие спинлока атомарны независимо от irql. Большинство процессоров предоставляют для этого специнструкции (x86 - xchg, arm - swp, mc68000 - tas и т.п.), в винде с каких-то пор используется lock bts. На однопроцессорных машинах вместо того, чтобы бессмысленно гонять такты по кругу, во время захвата спинлока просто повышается irql, а самого спинлока в обычном понимании нету, т.к. повышение irql на однопроцессорной машине уже само по себе исключает вероятность повторной попытки захвата другим потоком. Но в любом случае IRQL остаётся на уровне dispatch, как минимум, пока спинлок не освободят.

    Как я написал, поймал я наконец эту ситуацию в отладочном режиме. То, что два потока крутятся на dispatch level, не означает, что они не прерываются (не synch и не cli всё-таки), и что не может сработать отладочный брейкпоинт windbg.
     
  6. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    l_inc
    Не спорю.

    Кто тогда его освободит, если уровень dispatch? Тот же поток что и захватил спинлок или прерывание? А где многозадачность? Находится всё время в dispatch это ведь ахтунг.

    А какого dispatch на многоядерном?
     
  7. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Booster
    Э... А кто по Вашему должен освобождать спинлок кроме того, кто его захватил? Я захватываю спинлок, ни о чём не подозревая использую ресурс, а тут... раз, и какой-то чужой поток мой спинлок освобождает и уже мой однопользовательский ресурс используют два моих потока. В этом состоит Ваше предложение?
    Поэтому нежелательно держать спинлоки длительное время.
    Чтобы в пределах процессора не гонять лишние такты, если двум потокам на одном и том же процессоре понадобится спинлок. Иначе возможна такая ситуация: поток захватил спинлок и остался на passive, планирование передаёт контроль другому потоку, который хочет захватить спинлок. Другой поток в этом случае просто будет накручивать такты, пока его квант не закончится.
     
  8. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    l_inc
    Я не о времени, а о том dispatch накладывает дополнительные ограничения, что очень плохо.

    Теперь понял твою мысль - потоки выполняются на разных ядрах и происходит реальный спинлок с race condition. А разве нельзя посмотреть чем занимается в это время другое ядро? Ну или погоняй на одном ядре.
     
  9. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Booster
    Разумеется, накладывает. Вот пример вступившего в эти наложенные ограничения.
    Можно, но ловится эта ситуация нечасто, в отладочном режиме ещё реже, да и стартовать систему в отладочном режиме не всегда удобно. Когда отловил, наконец, этот deadlock, ума не хватило посмотреть стек потока на втором ядре... я даже не разбирался... сохранил в блокнот вывод и спать пошёл.
     
  10. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Только что удалось опять поймать дэдлок (третий раз за две недели) под отладчиком. Похоже, баг таки виндовый, хоть только аутпосту и не везёт попадаться на нём. Вот стек обоих потоков в момент дэдлока:
    Код (Text):
    1. 1: kd> !running -i
    2.  
    3. System Processors 3 (affinity mask)
    4.   Idle Processors 0
    5.  
    6.        Prcbs     Current   Next    
    7.   0    83902920  96aa2348            ................
    8.   1    805d1120  96aa4338            ................
    9.  
    10. 1: kd> !thread 96aa2348
    11. THREAD 96aa2348  Cid 0004.01e0  Teb: 00000000 Win32Thread: 00000000 RUNNING on processor 0
    12. Not impersonating
    13. DeviceMap                 8ca08dc0
    14. Owning Process            8654d420       Image:         System
    15. Attached Process          N/A            Image:         N/A
    16. Wait Start TickCount      21666          Ticks: 1745 (0:00:00:27.222)
    17. Context Switch Count      1595            
    18. UserTime                  00:00:00.000
    19. KernelTime                00:00:27.440
    20. Win32 Start Address afw (0x937c51de)
    21. Stack Init 95b55000 Current 95b54c78 Base 95b55000 Limit 95b52000 Call 0
    22. Priority 16 BasePriority 8 PriorityDecrement 0 IoPriority 2 PagePriority 5
    23. ChildEBP RetAddr  Args to Child              
    24. 95b549e8 975df139 838ed86f 96bab008 ce1155f8 nt!KefAcquireSpinLockAtDpcLevel+0x2a (FPO: [0,0,0])
    25. 95b54a68 84b7d0b0 02abb1e4 00000000 00000000 wanarp!WanNdisReceivePackets+0x217 (FPO: [Non-Fpo])
    26. 95b54a9c 84b6fbef 00bab008 ce1155f8 00000000 ndis!ndisMIndicateNetBufferListsToOpen+0xab (FPO: [Non-Fpo])
    27. 95b54c28 84ab057f 88fcb470 96bab008 00000000 ndis!ndisMDispatchReceiveNetBufferLists+0x7c (FPO: [Non-Fpo])
    28. 95b54c44 84adbccd 88fcb470 ce1155f8 00000000 ndis!ndisMTopReceiveNetBufferLists+0x2c (FPO: [Non-Fpo])
    29. 95b54c60 84adbca4 96a88978 ce1155f8 00000000 ndis!ndisFilterIndicateReceiveNetBufferLists+0x20 (FPO: [Non-Fpo])
    30. 95b54c7c 937b05a0 96a88978 ce1155f8 00000000 ndis!NdisFIndicateReceiveNetBufferLists+0x1b (FPO: [Non-Fpo])
    31. 95b54cb8 84adbccd 96a88178 ce1155f8 00000000 pacer!PcFilterReceiveNetBufferLists+0xd2 (FPO: [Non-Fpo])
    32. 95b54cd4 84adbca4 96b27258 ce1155f8 00000000 ndis!ndisFilterIndicateReceiveNetBufferLists+0x20 (FPO: [Non-Fpo])
    33. 95b54cf0 937c4677 96b27258 ce1155f8 00000000 ndis!NdisFIndicateReceiveNetBufferLists+0x1b (FPO: [Non-Fpo])
    34. WARNING: Stack unwind information not available. Following frames may be wrong.
    35. 95b54d2c 937c52f1 96b2a800 00000000 00000000 afw+0x3677
    36. 95b54d7c 839dff7a 96a7aa9c 3ae1c7b2 00000000 afw+0x42f1
    37. 95b54dc0 83848efe 937c51de 96a7aa9c 00000000 nt!PspSystemThreadStartup+0x9d
    38. 00000000 00000000 00000000 00000000 00000000 nt!KiThreadStartup+0x16
    39. 0: kd> !thread 96aa4338
    40. THREAD 96aa4338  Cid 0004.01e4  Teb: 00000000 Win32Thread: 00000000 RUNNING on processor 1
    41. Not impersonating
    42. DeviceMap                 8ca08dc0
    43. Owning Process            8654d420       Image:         System
    44. Attached Process          N/A            Image:         N/A
    45. Wait Start TickCount      21665          Ticks: 1893 (0:00:00:29.530)
    46. Context Switch Count      1566            
    47. UserTime                  00:00:00.000
    48. KernelTime                00:00:29.655
    49. Win32 Start Address afw (0x937c51de)
    50. Stack Init 95b5b000 Current 95b5ac78 Base 95b5b000 Limit 95b58000 Call 0
    51. Priority 16 BasePriority 8 PriorityDecrement 0 IoPriority 2 PagePriority 5
    52. ChildEBP RetAddr  Args to Child              
    53. 95b5a9e8 975df048 838ed86f 96bab008 86c5ac30 hal!KeAcquireSpinLockRaiseToSynch+0x3f (FPO: [0,0,0])
    54. 95b5aa68 84b7d0b0 02abb1e4 88f03358 00000000 wanarp!WanNdisReceivePackets+0x126 (FPO: [Non-Fpo])
    55. 95b5aa9c 84b6fbef 00bab008 86c5ac30 00000000 ndis!ndisMIndicateNetBufferListsToOpen+0xab (FPO: [Non-Fpo])
    56. 95b5ac28 84ab057f 88fcb470 96bab008 00000000 ndis!ndisMDispatchReceiveNetBufferLists+0x7c (FPO: [Non-Fpo])
    57. 95b5ac44 84adbccd 88fcb470 86c5ac30 00000000 ndis!ndisMTopReceiveNetBufferLists+0x2c (FPO: [Non-Fpo])
    58. 95b5ac60 84adbca4 96a88978 86c5ac30 00000000 ndis!ndisFilterIndicateReceiveNetBufferLists+0x20 (FPO: [Non-Fpo])
    59. 95b5ac7c 937b05a0 96a88978 86c5ac30 00000000 ndis!NdisFIndicateReceiveNetBufferLists+0x1b (FPO: [Non-Fpo])
    60. 95b5acb8 84adbccd 96a88178 86c5ac30 00000000 pacer!PcFilterReceiveNetBufferLists+0xd2 (FPO: [Non-Fpo])
    61. 95b5acd4 84adbca4 96b27258 86c5ac30 00000000 ndis!ndisFilterIndicateReceiveNetBufferLists+0x20 (FPO: [Non-Fpo])
    62. 95b5acf0 937c4677 96b27258 86c5ac30 00000000 ndis!NdisFIndicateReceiveNetBufferLists+0x1b (FPO: [Non-Fpo])
    63. WARNING: Stack unwind information not available. Following frames may be wrong.
    64. 95b5ad2c 937c52f1 96b2a800 00000000 00000000 afw+0x3677
    65. 95b5ad7c 839dff7a 96a7aac4 3ae127b2 00000000 afw+0x42f1
    66. 95b5adc0 83848efe 937c51de 96a7aac4 00000000 nt!PspSystemThreadStartup+0x9d
    67. 00000000 00000000 00000000 00000000 00000000 nt!KiThreadStartup+0x16
    Код потока в функции wanarp!WanNdisReceivePackets на нулевом ядре:
    Код (Text):
    1. loc_19032:                              ; CODE XREF: WanNdisReceivePackets(x,x,x,x,x)+F1 ^ j
    2.                 mov     eax, [ebp+var_3C]
    3.                 mov     esi, [eax+2]
    4.                 mov     ebx, offset _g_rlConnTableLock
    5.                 mov     ecx, ebx        ; SpinLock
    6.                 mov     [ebp+var_30], esi
    7. deadlock_place: call    ds:__imp_@KfAcquireSpinLock@4 ; KfAcquireSpinLock(x)
    8.                 cmp     esi, _g_ulConnTableSize
    9.                 mov     dl, al          ; NewIrql
    10.                 mov     [ebp+0Bh], dl
    11.                 mov     ecx, ebx        ; SpinLock
    12.                 jb      short loc_1905F
    13. loc_19057:                              ; CODE XREF: WanNdisReceivePackets(x,x,x,x,x)+207 v j
    14.                 call    ds:__imp_@KfReleaseSpinLock@8 ; KfReleaseSpinLock(x,x)
    15.                 jmp     short loc_19015
    16.  
    17. loc_1905F:                              ; CODE XREF: WanNdisReceivePackets(x,x,x,x,x)+133 ^ j
    18.                 mov     esi, ds:__imp_@KfReleaseSpinLock@8 ; KfReleaseSpinLock(x,x)
    19.                 call    esi ; KfReleaseSpinLock(x,x) ; KfReleaseSpinLock(x,x)
    Код потока на первом ядре в той же функции:
    Код (Text):
    1.                 mov     ecx, [esi+34h]  ; SpinLock
    2.                 mov     edi, ds:__imp_@KefAcquireSpinLockAtDpcLevel@4 ; KefAcquireSpinLockAtDpcLevel(x)
    3. deadlock_place: call    edi ; KefAcquireSpinLockAtDpcLevel(x) ; KefAcquireSpinLockAtDpcLevel(x)
    4.                 mov     ecx, ebx        ; _g_rlConnTableLock
    5.                 call    ds:__imp_@KefReleaseSpinLockFromDpcLevel@4 ; KefReleaseSpinLockFromDpcLevel(x)
    Как видно, поток на нулевом ядре виснет действительно при попытке захвата спинлока, который вот-вот должен был быть освобождён потоком на первом ядре. И виноват, очевидно, wanarp.sys.