CPU застрял на 100% на ПК клиента, какие-либо предложения по отладке? - PullRequest
3 голосов
/ 01 августа 2009

У меня тупиковая ситуация с одним из клиентов, использующих мое программное обеспечение. Из примерно 40 проданных копий нашего продукта (приложение, запрограммированное в .NET 2.0 с использованием VB.NET 2005), около 2 перестают отвечать на запросы, когда 1 ядро ​​двухъядерного процессора застряло на 100% (программа использует только одно ядро)

Наиболее логичным предположением является бесконечный цикл, вызывающий такое поведение, но это тысячи строк кода с множеством циклов. Это вся информация, которую я получил; Теперь, как вы предлагаете мне подойти к отладке этой проблемы?

EDIT: По сути, программное обеспечение отвечает за расчет суммы кредита, потраченного с использованием других устройств, таких как ПК и т. Д. Это программа управления Cybercafe, которая периодически дает сбой, т. Е. Вычитает кредит, когда происходит сбой. Он также выполняет другие действия в фоновом режиме, например, проверяет, не пришло ли время создать резервную копию базы данных.

EDIT: Решаемые. Это была самая маловероятная проблема. Access Database Engine, который я использовал в качестве СУБД, на самом деле является частью моего приложения, которая является проблематичной. Он испытывает трудности при работе со строкой - ТОЛЬКО ОДИН ИЗ ФРИГИНА - в одной из таблиц. Я не могу удалить его или иным образом добавить запись, относящуюся к этой строке в любой другой таблице; Даже MS Access 2007 заставляет процессор работать до 100%, когда я пытаюсь работать с этой строкой!

Простая команда «Сжать и восстановить» исправила все. Я думаю, что я буду вводить эту команду каждый раз, когда запускается мое приложение. Это предотвратит повторение этого.

Благодаря WinDbg я смог найти, в чем проблема. Я рекомендую всем научиться использовать его, потому что это экономит время.

Ответы [ 8 ]

7 голосов
/ 02 августа 2009

Установите windbg (отладчик Windows) на целевой машине. Вызовите отладчик и подключитесь к подозрительному процессу, запустите программу и дождитесь возникновения проблемы. Когда возникает проблема, вызовите следующую команду в командной строке отладчика

! Беглый

Это покажет, какие из ваших потоков занимают большую часть времени. Затем получите несколько потоков из этого потока, который потребляет большую часть ресурсов вашего процессора.

Вот пример:

0:015> !runaway

Время режима пользователя Время нити 0: 1074 0 дней 0: 00: 21.637 11: 137с 0 дней 0: 00: 02.792 4: 12с8 0 дней 0: 00: 00.530 9: 1374 0 дней 0: 00: 00.046 15: 13d0 0 дней 0: 00: 00.000 14: 1204 0 дней 0: 00: 00.000 13: 154с 0 дней 0: 00: 00.000 12: 144с 0 дней 0: 00: 00.000 10: 1378 0 дней 0: 00: 00.000 8: 1340 0 дней 0: 00: 00.000 7: 12f0 0 дней 0: 00: 00.000 6: 12d4 0 дней 0: 00: 00.000 5: 12d0 0 дней 0: 00: 00.000 3: 12c4 0 дней 0: 00: 00.000 2: 12c0 0 дней 0: 00: 00.000 1: 12b4 0 дней 0: 00: 00.000

Теперь предположим, что нам нужен стек вызовов для второго потока в списке, потока 11, поэтому сначала переключимся на поток 11. Это можно сделать, введя ~ 11s.

0:015> ~11s

eax = 03fbb270 ebx = ffffffff ecx = 00000002 edx = 00000060 esi = 00000000 edi = 00000000 eip = 77475e74 esp = 0572f60c ebp = 0572f67c iopl = 0 nv up ei pl zr na pe nc cs = 001b ss = 0023 ds = 0023 es = 0023 fs = 003b gs = 0000 efl = 00000246 Ntdll KiFastSystemCallRet: 77475e74 c3 ret

Теперь получите стек вызовов для этого потока, выполнив kp:

0:011> kp
ChildEBP RetAddr  
0572f608 77475620 ntdll!KiFastSystemCallRet
0572f60c 75b09884 ntdll!NtWaitForSingleObject+0xc
0572f67c 75b097f2 kernel32!WaitForSingleObjectEx+0xbe
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files\Mozilla Firefox 3.1 Beta 1\nspr4.dll - 
0572f690 10019a0b kernel32!WaitForSingleObject+0x12
WARNING: Stack unwind information not available. Following frames may be wrong.
0572f6ac 10015979 nspr4!PR_MD_WAIT_CV+0x8b
0572f6c4 10015763 nspr4!PR_GetPrimordialCPU+0x79
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files\Mozilla Firefox 3.1 Beta 1\xul.dll - 
0572f6e0 64d44d6a nspr4!PR_Wait+0x33
0572f708 64dbe67e xul!NS_CycleCollectorForget2_P+0x698a
0572f72c 10019b3f xul!gfxWindowsPlatform::FontEnumProc+0xfd4e
0572f734 10015d32 nspr4!PR_MD_UNLOCK+0x1f
0572f738 1001624b nspr4!PR_Unlock+0x22
0572f754 1001838d nspr4!PRP_TryLock+0x4cb
00000000 00000000 nspr4!PR_Now+0x109d

Команда kp напечатает параметры. Локальные переменные могут быть напечатаны с помощью DV.

В качестве альтернативы вы можете использовать Process Explorer из sysinternals.

Если все это невозможно, поскольку это удаленный клиентский компьютер, установите userdump, который создает файл дампа, который можно отправить вам для дальнейшего анализа. Вы можете создать пакетный файл, чтобы клиент вызывал userdump с правильными параметрами. Userdump - это инструмент от Microsoft, который можно загрузить с их веб-страницы.

4 голосов
/ 01 августа 2009

Если это бесконечный цикл, попробуйте подключить отладчик и нажать break. WinDbg идеально подходит для этого.

Эта техника также работает для случая, когда цикл просто повторяется слишком много раз, но в конечном итоге продолжается с остальным кодом. Для получения хорошего образца можно потратить пару минут на повторение процедуры.

Эта техника несколько раз спасла меня и хорошо работает и для зависших приложений:)

4 голосов
/ 01 августа 2009

Если возможно, получите дамп процесса и посмотрите трассировку стека.
Я никогда не делал этого, но он должен работать с VS / WinDbg и SOS (Son of Strike). Вот сообщение в блоге об этом.

2 голосов
/ 01 августа 2009

Вам придется очень тщательно опросить этих клиентов. Это не всегда легко, но это ваш единственный шанс сузить проблему.

Затем аккуратно добавьте трассировку, и не забудьте промывать в стратегических точках (или установить автоматическую заливку).

Но это может быть тонкая проблема синхронизации, которая исчезает из-за дополнительной задержки трассировки ...

2 голосов
/ 01 августа 2009

Используйте регистратор, такой как log4net , который вы можете представить в существующую кодовую базу с помощью postsharp . Записывайте все записи и выходы метода, поэтому вы должны найти неисправный метод. Тогда вы можете улучшить свою регистрацию, если она все еще требуется.

Похоже, что это работает и для vb.net, хотя у меня там нет опыта. Может быть, эта статья вам немного поможет.

2 голосов
/ 01 августа 2009

Что ж, вам нужно потренироваться там, где это круто. Что ваш клиент делает с программным обеспечением в то время? Что делает программа в первую очередь?

Возможно, вы захотите добавить в свой код много журналов и дать клиенту копию со всеми включенными журналами, что поможет вам отследить, где у них проблемы.

1 голос
/ 01 августа 2009

Может быть проблема с одноядерными и многоядерными процессорами, которые ведут себя по-разному, например, когда фоновый поток пытается обновить пользовательский интерфейс.

(И я признаю, что в темные времена я написал приложение, которое не разделяло чисто фоновые потоки и потоки пользовательского интерфейса и вызывало проблемы, когда многоядерные процессоры получили массовое распространение. Решением было вызвать SetProcessAffinity для ограничения приложения одноядерный)

Если это так, вы должны проверить, происходит ли 100% -ный ЦП только с особым типом ЦП и решает ли использование SetProcessAffinity эту проблему. Если да, вы знаете, где искать в своем коде.

0 голосов
/ 02 августа 2009

Может ли быть проблема с многопоточностью? "прерывисто" делает я думаю об этом. Получает ли программа сигналы / сообщения снаружи, как удаленное взаимодействие / DCOM / сокеты? Прогресс информация, относящаяся к таким сообщениям, представленная пользователю интерфейс

Однажды я обнаружил проблему с многопоточностью, потому что всегда использую много ассертов. Для начала была проверка работоспособности АССЕРТ сообщения, полученного через XML-RPC:

"<?xml " 

и ASSERT перехватил перезапись памяти сообщения. От осмотр это оказалось из-за отсутствия замка в критический раздел. Это обнаружение было возможно только потому, что проблема была поймана так рано ASSERT (и это случалось достаточно часто, чтобы быть обнаруженным).

Это не очень конкретный или направленный совет, но мой предложение заключается в том, чтобы добавить ASSERT в местах, которые могут быть затронул проблему с потоками.

Обратите внимание, что запуск ASSERT не обязательно означает прекращение программа или выбросить сообщения. АССЕРТЫ могут быть вместо этого перенаправляется в файл журнала, включая полный стек след во время стрельбы ASSERT.

...