Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2013.11.03;
Скачать: [xml.tar.bz2];

Вниз

Падение приложения, 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 вся ветка

Форум: "Прочее";
Текущий архив: 2013.11.03;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.57 MB
Время: 0.004 c
2-1357887539
vrem
2013-01-11 10:58
2013.11.03
Память естся, подскажите как исправить для такого вызова:


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


1-1316688285
denkop
2011-09-22 14:44
2013.11.03
TImage над TStringGrid


2-1359817506
TSas
2013-02-02 19:05
2013.11.03
Не могу получить свойство Name элемента вебстраницы


15-1368728640
Cynic
2013-05-16 22:24
2013.11.03
Разработчик интерфейсов





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский