Вниз
Скачать: CL | DM;

Падение приложения, crash без визуализации   Найти похожие ветки 

← →
Es   (2013-05-14 18:22) [0]

Есть приложение, работает на сервере (в смысле, что на Win server 2008), но не в виде сервиса, а как обычное GUI приложение + много потоков в виде обработчиков.

Беда в том, что иногда приложение просто исчезает. Смотрят - а его нету в процессах, никаких сообщений, ну как будто не было.
Приложение под еврикой, но никаких .elf отчетов рядом не обнаруживается.

Возникает вопрос - как копать и куда. В каких случаях windows вообще может терминировать процесс, причем так втихую? Как искать место затыка?

Если это исключение в главном потоке, то почему оно не перехватывается стандартным кодом VCL?


← →
Плохиш ©   (2013-05-14 18:34) [1]

Смотри логи виндовс.


← →
Дмитрий С ©   (2013-05-14 18:34) [2]

А в журнале про это что-нибудь написалось?


← →
Es   (2013-05-14 18:35) [3]

как именно


← →
Rouse_ ©   (2013-05-14 18:39) [4]


> В каких случаях windows вообще может терминировать процесс,
>  причем так втихую? Как искать место затыка?

90 процентов что портится стек, а раз стека нет - значит нет никаких SEH фреймов и исключений, включая глобальный обработчик, собстенно о этом говорит и несрабатывание EurekaLog, который работает на перехвате вызова raise.
Если ручками со стеком ничего не делаешь - значит кривая работа с памятью.


← →
Es   (2013-05-14 18:44) [5]

нашел один из крешей в eventvwr:

Faulting application OfflineServer.exe, version 1.0.1.103, time stamp 0x2a425e19, faulting module ntdll.dll, version 6.0.6002.18541, time stamp 0x4ec3e3d5, exception code 0xc0000005, fault offset 0x00041440, process id 0x2ae0, application start time 0x01ce4ed2616a69ba.


← →
Es   (2013-05-14 18:48) [6]

Rouse_, а делать то что, как можно искать проблему? Приложение достаточно большое, чтобы каждую строчку просматривать, да и утопический это подход.

Как я понимаю, ставить try..except по коду и пытаться писать исключения в лог - это тоже не прокатит.

А куда копать тогда...


← →
Плохиш ©   (2013-05-14 18:50) [7]


> 0xc0000005

Access Violation


← →
clickmaker ©   (2013-05-14 18:51) [8]

> exception code 0xc0000005

Access denied
Смотри, куда твоя тулза просит доступ, и где ей может быть отказано.


← →
Rouse_ ©   (2013-05-14 18:52) [9]

c0000005 - AccessViolation
твой оффсет: 0х41440 + база загрузки
Запускай приложение и становись бряком на этот адрес - там уже и смотри.


← →
Rouse_ ©   (2013-05-14 18:54) [10]

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


← →
Rouse_ ©   (2013-05-14 19:02) [11]

зы: забыл, в случае ntdll адрес рассчитываешь $41440 + GetModuleHandle(ntdll32), переходишь в CPU View, ставиш бряк, запускаешь процесс, ждеш сработки - по стеку вызовов уточняешь что за функция расположена по данному адресу (в случае если в отладчике не размапятся имена, обычно они видны).
Потом переопределяешь ее на свой вызов (любым доступным способом) и логируешь вызовы, пока не упрешся в падение.
Если я прав и падает из-за порчи стека, то полагаться на try..finally смысла не имеет - они не сработают. В этом случае используй механизм VEH
http://msdn.microsoft.com/en-us/library/windows/desktop/ms681420(v=vs.85).aspx


← →
Es   (2013-05-14 19:15) [12]

Rouse_, нихрена не понял арифметики.

Вообще, если падает внутрях ntdll - по идее, причем тут мой модуль? Получается, код ntdll сделал нечто такое, что некорректно сработало с памятью, верно?

>fault offset 0x00041440

он пишется относительно чего? Если относительно "нуля" - то я так понимаю, просто по этому адресу и располагается Ntdll?


← →
Es   (2013-05-14 19:16) [13]

Rouse_, а, кажется понял. Винда пишет адрес:

>fault offset 0x00041440

относительно начала модуля, который она указывает:

>faulting module ntdll.dll

?


← →
Rouse_ ©   (2013-05-14 19:18) [14]

угу


← →
Es   (2013-05-14 19:23) [15]

все равно непонятно - а почему это исключение в ntdll не перехватывается программой?

Какой-то настолько глобальный трындец, что портится стек, а при этом в некую неизвестную функцию ntdll передаются параметры (ну собственно из-за стека), которые заставляют ntdll обратиться в непонятную область памяти?


← →
Es   (2013-05-14 19:27) [16]

большая беда в том, что падения бывают раз в неделю при круглосуточной работе. А бывают и 3 раза в день...

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

Плюс программа крутится на windows server 2008, а у меня Win 7 рабочая.

Могу вытащить ntdll с той машины, но как по смещению понять функцию? ...


← →
Rouse_ ©   (2013-05-14 19:37) [17]


> а почему это исключение в ntdll не перехватывается программой?

Потомучто в случае разрушения стека механизм отлавливания исключений перестает работаеть, ибо SEH фреймы работают то-же через стек.

Функция в NTDLL может работать с памятью, ну например какой-нить VirtualFree которому ты передал адрес страницы со стека или еще чего.


> Могу вытащить ntdll с той машины, но как по смещению понять
> функцию? ...

В любом отладчике открыть и посотреть что там расположено.


← →
Es   (2013-05-14 21:51) [18]

воспользовался статьей: http://www.twintechs.com/2008/11/how-to-find-what-function-is-at-a-dll-offset-without-having-debug-symbols/

Запустил OllyDbg на искомой машине, подгрузил туда ntdll.dll
Он начинался с адреса: 76EE1000. В статье прочитал, что это значит базовый адрес: 76EE0000

Приплюсовал свое смещение 41440, получилось: 76F21440
Получилось такое:

http://img14.imageshost.ru/img/2013/05/14/image_51926b0405576.png

(инструкция MOV EDI, EDI - могло из-за этого?)


← →
Es   (2013-05-14 21:51) [19]

Пошел вверх до значка "$" - написано, что так отладчик обозначает функции, получился адрес: 76F21349

http://img14.imageshost.ru/img/2013/05/14/image_51927c3d40728.png

Далее сказано идти в " Debug > Call DLL Export"... И офигеть, там функции отсортированы не по адресам... Просмотрел весь список!!! Убил глаза в хлам... Функции с началом адреса 76F21349 не нашел...


← →
Es   (2013-05-14 21:55) [20]

на всякий случай выкладываю целевой ntdll.dll - http://webfile.ru/6519741 (526 кбайт, нужно выбрать "скачать напрямую"), может кто подсобит...


← →
clickmaker ©   (2013-05-14 22:04) [21]

> MOV EDI, EDI - могло из-за этого?)

вряд ли. Это просто NOP по сути


← →
clickmaker ©   (2013-05-14 22:13) [22]

может быть, дело в этом: http://habrahabr.ru/post/90377/


← →
Rouse_ ©   (2013-05-14 22:17) [23]

Из-за этого не могло.
MOV EDI, EDI - это пролог MS API использующих технологию HOT_PATCH.
В данном случае я опознаю данную функцию как RaiseException.
В итоге ты просто получил адрес вызова финального исключения в отсутствие обработчика оного.

Получается теперь у тебя только один способ и остался - использование VEH.
Установи VEH обработчик и попробуй логировать исключения через него, с целью получить адрес вылета.

Есть нюанс - VEH работает перед SEH, поэтому ты будешь получать море исключений, пока не выйдешь на то, которое тебе нужно.


← →
Rouse_ ©   (2013-05-14 22:22) [24]


> clickmaker ©   (14.05.13 22:04) [21]

Тезка, не болтайте ерундой :)
Изменение регистров в случае MOV отличается от штатного поведения NOP.

Ну и раз уж пошла ссылка на хабр, то для Delphi сообщества более адекватной и менее ошибочной (даже в плане изложения материала) будет данная ссылка :)
http://habrahabr.ru/post/178393/


← →
clickmaker ©   (2013-05-14 22:46) [25]

> Тезка, не болтайте ерундой :)

собственно, все ссылки в гугле по mov edi,edi и ведут на хот-патч


← →
Rouse_ ©   (2013-05-14 22:57) [26]


> clickmaker ©   (14.05.13 22:46) [25]
> > Тезка, не болтайте ерундой :)
>
> собственно, все ссылки в гугле по mov edi,edi и ведут на
> хот-патч

Сань, в приведенной тобой ссылке нет упоминания о хотпатче.
Более того есть куча ошибок, о части которых я уведомил автора статьи.
К примеру (даже не буду рассматривать пропуск стаба): "Кроме того, если размер функции меньше 5 байт, перехват просто невозможен."

Это есть неверно.

Ну либо:

"3. Скопировать туда первые 5 байт исходной функции до установки туда перехватчика."

С учетом что максимальный размер инструкции может быть равен 14-ти байтам, я не думаю что разрезание инструкции по ее середке будет оправдано :)


← →
clickmaker ©   (2013-05-14 23:13) [27]

> [26] Rouse_ ©   (14.05.13 22:57)

да хрен с ней, со статьей. Я предположил просто, не может ли попытка этого хот-патча привести к исключению...


← →
Rouse_ ©   (2013-05-14 23:29) [28]


> clickmaker ©   (14.05.13 23:13) [27]

Если правильно его использовать - то нет, тем-более данная метода обычно выполняется сторонним приложением, а не тем, которое падает.
При неправильном использовании можем вылезти на вот такие вот нюансы: http://alexander-bagel.blogspot.ru/2012/11/debuger-2.html#false_disasm

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


← →
Es   (2013-05-15 00:08) [29]


> MOV EDI, EDI - это пролог MS API использующих технологию
> HOT_PATCH.
> В данном случае я опознаю данную функцию как RaiseException.
>
> В итоге ты просто получил адрес вызова финального исключения
> в отсутствие обработчика оного.

ох долго мне переваривать эти строки...

Насколько я понял, HOT_PATCH - это такая штука, что в начало функции вставляется двухбайтовая команда mov EDI, EDI (которая ничего по сути не делает), чтобы потом было легче начало функции перезатереть и переправить на свою функцию (аля перехват)?

Уже тут я не понял. Если рассмотреть вывод винды:

>fault offset 0x00041440

я так понимаю, относительно начало модуля ntdll.dll по указанному смещению находилась инструкция, выполнение которой и завершилось исключением? Обработка исключения при этом нифига не произошла, потому что к тому времени стек был нагло испохаблен.

Но по этому адресу, если я все сделал правильно, находится инструкция MOV EDI, EDI (безобидная). Означает ли это, что вместо данной инструкции на момент выполнения программы там находилась другая инструкция?

Может, тогда стоит запустить программу и просто считать какая реально команда находится в загруженном приложении по этому смещению?

Также я не понял фразу:

> В данном случае я опознаю данную функцию как RaiseException.

что имеется в виду под "данную функцию"? И каким образом произошло опознание, по представленной картинке?


← →
Es   (2013-05-15 00:18) [30]


> Установи VEH обработчик и попробуй логировать исключения
> через него, с целью получить адрес вылета.

вот не понял опять :(
Я так попытался прочитать про VEH, как я понял это возможность перехватывать исключения. При этом я получу информацию о них, несмотря на то, что callstack разрушен. Но я не понял:

1) почему собственно обычные исключения перестают работать, если callstack испоганен? Исключения же не в стеке хранятся?

2) каким все таки образом поможет VEH? Вот получу я управление после исключения.. а дальше? (


← →
Cobalt ©   (2013-05-15 01:23) [31]

может на серваке какая утилита криво перехватывает функции?
Сравни загруженные в АП длл-ки


← →
Es   (2013-05-15 02:15) [32]

да не, исключено почти. Корпоративный сервер, особо никакого лишнего софта (хакерского).

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


← →
Германн ©   (2013-05-15 02:51) [33]


> ох долго мне переваривать эти строки...


> > Установи VEH обработчик и попробуй логировать исключения
> > через него, с целью получить адрес вылета.
>
> вот не понял опять :(
>

Ох действительно долго. Ну разве что Розыч почему-то захочет помочь. :)


← →
Германн ©   (2013-05-15 03:27) [34]


> Ну разве что Розыч почему-то захочет помочь. :)
>

Как-то иначе я его совет: "Установи VEH обработчик" я просто не воспринимаю. :)
Понимаю, что Саша живёт в своём мире. :)


← →
Dimka Maslov ©   (2013-05-15 08:28) [35]

В своё время я долго блися с подобной проблемой падения многопоточного сервера. Как я понял это происходит из-за плохой синхронизации потоков при обращении к менеджеру памяти. Причём, как на С++, так и на Delphi. Возможных решений два - написать свой менеджер памяти или сделать приложение службой, заставив систему перезапускать его в случае сбоя. Второе решение гораздо проще.


← →
Rouse_ ©   (2013-05-15 10:31) [36]


> что имеется в виду под "данную функцию"? И каким образом
> произошло опознание, по представленной картинке?

Немного промахнулся, это LdrInitializeThunk

.text:77F11440 ; __stdcall LdrInitializeThunk(x, x)
.text:77F11440                 public _LdrInitializeThunk@8
.text:77F11440 _LdrInitializeThunk@8 proc near
.text:77F11440
.text:77F11440 arg_0           = dword ptr  8
.text:77F11440 arg_4           = dword ptr  0Ch
.text:77F11440
.text:77F11440                 mov     edi, edi
.text:77F11442                 push    ebp
.text:77F11443                 mov     ebp, esp
.text:77F11445                 push    [ebp+arg_4]
.text:77F11448                 push    [ebp+arg_0]
.text:77F1144B                 call    _LdrpInitialize@8 ; LdrpInitialize(x,x)
.text:77F11450                 push    1
.text:77F11452                 push    [ebp+arg_0]
.text:77F11455                 call    _ZwContinue@8   ; ZwContinue(x,x)
.text:77F1145A                 push    eax
.text:77F1145B                 call    _RtlRaiseStatus@4 ; RtlRaiseStatus(x)
.text:77F11460                 int     3               ; Trap to Debugger
.text:77F11461                 nop
.text:77F11462                 nop
.text:77F11463                 nop
.text:77F11464                 nop
.text:77F11465                 nop
.text:77F11465 _LdrInitializeThunk@8 endp


Что впрочем тоже мало что нам дает.


> 1) почему собственно обычные исключения перестают работать,
>  если callstack испоганен? Исключения же не в стеке хранятся?
>

Исключения нет, но в стеке размещаются SEH фреймы, которые и перехватывают исключения.


> 2) каким все таки образом поможет VEH? Вот получу я управление
> после исключения.. а дальше? (

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


← →
Плохиш ©   (2013-05-15 10:36) [37]

Вроде в Delphi тоже Remote Debugger есть.


← →
Es   (2013-05-15 12:15) [38]


> Немного промахнулся, это LdrInitializeThunk

классно. А как ты узнал, что это LdrInitializeThunk?

У меня адрес исключения - 76F21440, на твоей системе в той же DLL я так понял это 77F11440, но откуда столько строк под этим адресом? Если был бы приведен листинг:

.text:77F11440                 mov     edi, edi
.text:77F11442                 push    ebp
.text:77F11443                 mov     ebp, esp
.text:77F11445                 push    [ebp+arg_4]
.text:77F11448                 push    [ebp+arg_0]
.text:77F1144B                 call    _LdrpInitialize@8 ; LdrpInitialize(x,x)
.text:77F11450                 push    1
.text:77F11452                 push    [ebp+arg_0]
.text:77F11455                 call    _ZwContinue@8   ; ZwContinue(x,x)
.text:77F1145A                 push    eax
...
...


то это прям совпадало бы с тем, что я видел. Но откуда эта надстройка:

.text:77F11440 ; __stdcall LdrInitializeThunk(x, x)
.text:77F11440                 public _LdrInitializeThunk@8
.text:77F11440 _LdrInitializeThunk@8 proc near
.text:77F11440
.text:77F11440 arg_0           = dword ptr  8
.text:77F11440 arg_4           = dword ptr  0Ch
.text:77F11440


Это говорит о том, что по адресу 77F11440 находится непосредственно точка входа в LdrInitializeThunk?

А как он может быть точкой исключения? Управление передано по этому адресу... и тут же исключение? Там же никакого кода, первая команда же MOV EDI, EDI - она же ничего не делает!
Не понимаю... Что за адрес исключения тогда в журнале винды? (


← →
Rouse_ ©   (2013-05-15 12:20) [39]


> классно. А как ты узнал, что это LdrInitializeThunk?

Ты открывал в OllyDebug, а у меня лицензионная IDA Pro + установленные символы, поэтому информации выдается в разы больше.


> Там же никакого кода, первая команда же MOV EDI, EDI - она
> же ничего не делает!

Ну вариантов на самом деле много, самый простой - по данному адресу были выставлены неверные аттрибуты страницы, что и привело к падению.
Либо второй вариант, из-за срыва стека получить точный адрес ошибки не удалось и вылез вот этот вот оффсет.


← →
Es   (2013-05-15 12:22) [40]


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

а что значит точный адрес исключения? Почему адрес исключения винды не точный? Она ведь по идее должна отловить именно указатель на ту инструкцию, которая вызвала исключение?


> и сможешь вытащить всю цепочку вызовов, чтобы определить
> какой именно код вызвал падение.

а как я вытащу цепочку вызовов, если callstack"у хана на тот момент уже? (



Страницы: 1 2 3 вся ветка

Скачать: CL | DM;



Память: 0.57 MB
Время: 0.005 c
2-1360311329
Camaro
2013-02-08 12:15
2013.11.03
снизить цену на определенный %


11-1248443105
DevilDevil
2009-07-24 17:45
2013.11.03
Горизонтальный ScrollBar


15-1368541324
Es
2013-05-14 18:22
2013.11.03
Падение приложения, crash без визуализации


4-1268010549
JohnJ
2010-03-08 04:09
2013.11.03
закрепить панель задач


2-1360085593
Novice
2013-02-05 21:33
2013.11.03
Выделение строки ListView другим цветом




   Наверх