Господа, будьте снисходительны, не бросайтесь сразу штрафовать за, как вам кажется, глупые вопросы - beginners на то и beginners.
Выложить 40 метров? Подозреваю что не будут качать :)16.07.08 10:36 Число просмотров: 1622 Автор: Ustin <Ustin> Статус: Elderman Отредактировано 16.07.08 10:39 Количество правок: 3
> 1) Насчет map-файла, сначала идет номер секции, потом > смещение. > Ты бы выложил куда-нибудь этот EXE-файл, тебе сразу скажут > – что такое "buh+0x60cdbe" :) Выложить 40 метров? Подозреваю что не будут качать :)
Если нет других путей - то конечно, не вопрос...
А надо в итоге просто увидеть именованый стек вызова функций\методов в момент падения винды. А дальше попробуем "слабать кролика"
> 2) Если для компонент DeveloperExpress / FastReport нет > исходников, > то можно перекрыть функцию EnumFontFamiliesEx (это > называется API hook). Если она не будет вызываться вообще - подозреваю, что все бухи останутся без отчётов... Перекрывать её вызовом, в конечном итоге, самой себя (плаваю в вопросе, может это и не так) - есть ли смысл?
Случилась засада: самописная аппликуха при старте на W2k3 SP1, SP2 периодически (достаточно редко, раз примерно в 1000 запусков) валит венду с вердиктом:
Такая штука происходит на разных машинах, конфигурация и работоспособность железа вроде как сомнения не вызывает (глюк проявляется как на физических, так и на виртуальных серверах). "Откатить" программу до версии, в которой этого не происходит не представляется возможным, т.к. глюк крайне нерегулярен и софтина постоянно изменяется группой разрабов.
Подскажите в какую сторону копать?
Последние обновления от MS установлены?14.07.08 22:12 Автор: Den <Денис Т.> Статус: The Elderman
> Случилась засада: самописная аппликуха при старте на W2k3 > SP1, SP2 периодически (достаточно редко, раз примерно в > 1000 запусков) валит венду с вердиктом: > > Analyzing "C:\temp\dmptmn\MEMORY.DMP", please wait... Done. > Crash date: Wed Jun 25 16:41:38.593 2008 (GMT+3) > Stop error code: 0x8E > Process name: buh.exe > Probably caused by: win32k.sys ( win32kIsAnyCharsetDbcs+38 > ) > > Такая штука происходит на разных машинах, конфигурация и > работоспособность железа вроде как сомнения не вызывает > (глюк проявляется как на физических, так и на виртуальных > серверах). "Откатить" программу до версии, в которой этого > не происходит не представляется возможным, т.к. глюк крайне > нерегулярен и софтина постоянно изменяется группой > разрабов. > > Подскажите в какую сторону копать? Взять сислог и апплог с предыдушего успешного и проблемного старта и сравнить.
Мне помогло сделать рукописный (не свой, с потерянной поддержкой) системный сервис зависимым от остальных сервисов, которые должны 100% должны грузиться. Оказалось, иногда медленно запускался локальный DNS, и приложение чего-то недогоняло вовремя и рушилось.
Решительно никаких отличий :(09.07.08 18:02 Автор: Ustin <Ustin> Статус: Elderman Отредактировано 09.07.08 18:04 Количество правок: 1
> Взять сислог и апплог с предыдушего успешного и проблемного > старта и сравнить. Решительно никаких отличий, более того, аппликуха явно ни в какие eventlog не пишет, кроме как падает сама (винда это корректно фиксирует). А проблема стоит очень остро - несколько раз в день (где-то 100 клиентов в среднем) умирает ТС с этой прогой на борту. А M$ отбоярилась наличием платного суппорта...
> Мне помогло сделать рукописный (не свой, с потерянной > поддержкой) системный сервис зависимым от остальных > сервисов, которые должны 100% должны грузиться. Оказалось, > иногда медленно запускался локальный DNS, и приложение > чего-то недогоняло вовремя и рушилось. Спасибо, учту обязательно.
Поддержка в MS27.06.08 23:43 Автор: Ustin <Ustin> Статус: Elderman Отредактировано 27.06.08 23:46 Количество правок: 1
На этот вопрос на микрософте ответили:
Если у вас есть подписка Technet, то в ее рамках можно открыть инцидент в поддержке, либо для начала написать в подходящую managed news group - этот сервис тоже есть в подписке.
Я ответил:
Пожалуйста подскажите, возможны ли другие варианты: technet-подписки ни у меня, ни у других людей из компании нет. Что необходимо сделать, чтобы её получить? Возможны ли другие способы инициирования проблемы?
И тишина.
Никто не может подсказать\посодействовать нубу в понимании как-таки открыть инцидент по данной проблеме?
Если еще актуально11.07.08 22:33 Автор: Neznaika <Alex> Статус: Member
> То можно снять полный дамп средствами самого WinDbg > (из пакета "Debugging Tools for Windows"). > > Для этого там есть специальный скрипт на VB: "adplus.vbs" > Т.е, просто создаем *.bat файл типа этого: Не совсем понял, можно сделать дамп памяти процесса "по заказу"? Но дело в том, что это проявляется далеко не каждый раз
> ====================< Cut here <==================== > mkdir AppTrace > call adplus -quiet -crash -pn MyApp.exe -o %cd%\AppTrace -y > "SRV*symbols*http://msdl.microsoft.com/download/symbols;%Sy > stemRoot%\system32\;" > ====================< Cut here <==================== > > Здесь: > MyApp.exe – EXE-файл, который падает > AppTrace – папка, в которую будут сохраняться дампы
Про полный дамп: получили (сервер аж в Омске, надо теперь вытягивать оттуда), ограничив винде память 2мя гигами
Не "по заказу" - а когда реально упадет14.07.08 16:40 Автор: Neznaika <Alex> Статус: Member
---
KD на !analyze -v пишет:
ERROR: Symbol file could not be found. Defaulted to export symbols for buh.exe
(buh.exe - та самая программа, которая падает)
Поскольку ламер, подскажите пожалуйста, что надо сделать чтобы выражения типа buh+0x5db7 превратить во что-то осмысленное? Delphi может генерировать .map файлы...
Во-первых, молодец – что снял дамп.14.07.08 22:34 Автор: Neznaika <Alex> Статус: Member
Как правильно сказал Сергей, “map файл - это и есть символы”.
Тебе надо просто взять *.map, для которого у тебя есть дамп и найти в нем последнюю функцию, которая далее вызывает EnumFontFamiliesEx. Для того дампа, который ты выложил – вызов идет с адреса “buh+0x60cdbe”. Т.е. в файле *.map надо найти самое близкое значение, меньшее чем 60cdbe. Это и будет функция, в которой все падает.
В-третьих. Сдается мне, что здесь - даже и без *.map файла - все понятно.
Ваша программа вызывает системную функцию EnumFontFamiliesEx. Одним из параметов EnumFontFamiliesEx является callback-функция (функция обратного вызова; т.е, программист сам эту функцию не вызывает, она вызывается системой Windows). И эта callback-функция у вас написана с ошибкой. Возможно, в ней не проверяются входные параметры. Или она не обьявлена как экпортируемая. Или она обьявлена как fastcall. Или она пишет в область памяти, которая не проинициализирована. Или еще что-нибудь.
Что надо сделать:
1) На всякий случай, я бы собрал еще несколько дампов, чтобы убедиться –
что падает именно здесь.
2) Далее, надо сказать разработчикам – что программа падает при вызове EnumFontFamiliesEx. Обычно мест, где эта функция вызывается немного, максимум два-три. Пусть самым тщательным образом проверят все эти вызовы.
Как это можно исправить:
a) Можно заменить EnumFontFamiliesEx на более простой аналог EnumFontFamilies;
b) Можно попробовать заменить callback-функцию на “пустышку”, которая ничего реально не делает;
c) В крайнем случае – можно выкинуть все вызовы к EnumFontFamiliesEx, я думаю – что в бухгалтерской программе без этой функции вполне можно обойтись.
Удачи!
В map-файле есть длиинная последовательность вида15.07.08 10:00 Автор: Ustin <Ustin> Статус: Elderman Отредактировано 15.07.08 10:06 Количество правок: 1
> Тебе надо просто взять *.map, для которого у тебя есть дамп > и найти в нем последнюю функцию, которая далее вызывает > EnumFontFamiliesEx. Для того дампа, который ты выложил – > вызов идет с адреса “buh+0x60cdbe”. Т.е. в файле *.map надо > найти самое близкое значение, меньшее чем 60cdbe. Это и > будет функция, в которой все падает. В map-файле есть длиинная последовательность вида
Address Publics by Name
0001:00AC3E44 AAMake..TAAMakeForm
0004:0000B498 AAMake.AAMakeForm
...
---
, а в конце написано Program entry point at 0002:00021748
Как соотнести “buh+0x60cdbe” с 0001:00AC3E44? Адресов порядка 60cс00 - 60ce00 в .map не нашёл...
> > В-третьих. Сдается мне, что здесь - даже и без *.map файла > - все понятно. > Ваша программа вызывает системную функцию > EnumFontFamiliesEx. Одним из параметов EnumFontFamiliesEx > является callback-функция (функция обратного вызова; т.е, > программист сам эту функцию не вызывает, она вызывается > системой Windows). И эта callback-функция у вас написана с > ошибкой. Возможно, в ней не проверяются входные параметры. > Или она не обьявлена как экпортируемая. Или она обьявлена > как fastcall. Или она пишет в область памяти, которая не > проинициализирована. Или еще что-нибудь. В программе используется всякая дрянь типа DeveloperExpress и FastReport, боюсь что им вызов EnumFont* необходим...
> Что надо сделать: > 1) На всякий случай, я бы собрал еще несколько дампов, > чтобы убедиться – > что падает именно здесь. Убедился - падает именно здесь на разном железе на Win2k3 Standart + TS
> 2) Далее, надо сказать разработчикам – что программа падает > при вызове EnumFontFamiliesEx. Обычно мест, где эта функция > вызывается немного, максимум два-три. Пусть самым > тщательным образом проверят все эти вызовы. Разработчики занимаются логикой :) и на винде не пишут, потому как "долго" и, сильно подозреваю, не умеют. Этот падёж приходится решать, так как народу на TS становится больше и глюк начинает проявляться чаще. Откатить версию до состояния "работает" возможности нет, т.к. код не очень managed + каждый божий день делается новая логика, в общем случае не совместимая с предыдущей
> Как это можно исправить: > a) Можно заменить EnumFontFamiliesEx на более простой > аналог EnumFontFamilies; Честно говоря, беглый просмотр исходников компонентов показал 11 мест только в исходниках компонентов, есть ещё несколько вхождений в .dcu (delphi compiled unit, получается после компиляции модулей, то из чего потом exe линкуется - бывает что компоненты распространяются не в виде исходных текстов, а в виде таких вот dcu). Поэтому, возможно, есть смысл поставить "пустышку" немного выше...
> Удачи!
Уточнение15.07.08 21:10 Автор: Neznaika <Alex> Статус: Member
1) Насчет map-файла, сначала идет номер секции, потом смещение.
Ты бы выложил куда-нибудь этот EXE-файл, тебе сразу скажут – что такое "buh+0x60cdbe" :)
2) Если для компонент DeveloperExpress / FastReport нет исходников,
то можно перекрыть функцию EnumFontFamiliesEx (это называется API hook).
Выложить 40 метров? Подозреваю что не будут качать :)16.07.08 10:36 Автор: Ustin <Ustin> Статус: Elderman Отредактировано 16.07.08 10:39 Количество правок: 3
> 1) Насчет map-файла, сначала идет номер секции, потом > смещение. > Ты бы выложил куда-нибудь этот EXE-файл, тебе сразу скажут > – что такое "buh+0x60cdbe" :) Выложить 40 метров? Подозреваю что не будут качать :)
Если нет других путей - то конечно, не вопрос...
А надо в итоге просто увидеть именованый стек вызова функций\методов в момент падения винды. А дальше попробуем "слабать кролика"
> 2) Если для компонент DeveloperExpress / FastReport нет > исходников, > то можно перекрыть функцию EnumFontFamiliesEx (это > называется API hook). Если она не будет вызываться вообще - подозреваю, что все бухи останутся без отчётов... Перекрывать её вызовом, в конечном итоге, самой себя (плаваю в вопросе, может это и не так) - есть ли смысл?
Судя по тому, что я увидел, кролика сделать будет непросто16.07.08 23:15 Автор: amirul <Serge> Статус: The Elderman
> Выложить 40 метров? Подозреваю что не будут качать :) > Если нет других путей - то конечно, не вопрос... > А надо в итоге просто увидеть именованый стек вызова > функций\методов в момент падения винды. А дальше попробуем > "слабать кролика"
Мое предположение: в результате race-а что то страшное происходит с DC (причем сам по себе он остается валидным - портятся только какие то глубинные структуры) и в один прекрасный момент при попытке работы с этим DC валится win32k. Чтобы сделать кролика тебе придется более менее повторить все рейсы, которые происходят в твоей программе (причем порча на DC может наводиться каким нибудь совершенно левым кодом: как с битым хипом - кто-то попортит хип, а падает в результате какой нибудь совершенно безобидный free).
Если бага репродюсится более менее стабильно, то ЕДИНСТВЕННЫМ реальным способом ее локализовать является постепенное выкусывание функционала, причем лучше всего что то типа бинарного поиска: откусили примерно половину кода - если продолжает падать - ищем в оставшемя, если перестало - в откусанном.
Других путей много - беда в том, что обьяснять долго16.07.08 19:25 Автор: Neznaika <Alex> Статус: Member Отредактировано 16.07.08 21:51 Количество правок: 1
> > В-третьих. Сдается мне, что здесь - даже и без *.map > файла > > - все понятно. > > Ваша программа вызывает системную функцию > > EnumFontFamiliesEx. Одним из параметов > EnumFontFamiliesEx > > является callback-функция (функция обратного вызова; > т.е, > > программист сам эту функцию не вызывает, она > вызывается > > системой Windows). И эта callback-функция у вас > написана с > > ошибкой. Возможно, в ней не проверяются входные > параметры. > > Или она не обьявлена как экпортируемая. Или она > обьявлена > > как fastcall. Или она пишет в область памяти, которая > не > > проинициализирована. Или еще что-нибудь. > В программе используется всякая дрянь типа DeveloperExpress > и FastReport, боюсь что им вызов EnumFont* необходим...
Если callback функция (та, ссылка на которую передается в функцию EnumFontFamiliesEx) не очень большая, то исходник в студию.
Куча спама, вроде бы ничего крамольного...15.07.08 19:09 Автор: Ustin <Ustin> Статус: Elderman
function EnumFontsProc(var LogFont: TLogFont; var TextMetric: TTextMetric;
FontType: Integer; Data: Pointer): Integer; stdcall;
begin
TStrings(Data).AddObject(LogFont.lfFaceName, Pointer(FontType and TRUETYPE_FONTTYPE <> 0));
Result := 1;
end;
---
function EnumFontsProc2(AFontLoader: TcxFontLoader; const ALogFont: TLogFont;
AFontType: DWORD): Integer;
var
AFaceName: string;
begin
AFaceName := ALogFont.lfFaceName;
if (AFontLoader.FontList.IndexOf(AFaceName) = -1) and
IsValidFontCondition(AFontLoader.FFontTypes, ALogFont, AFontType) then
begin
if ALogFont.lfCharSet = SYMBOL_CHARSET then
AFontType := AFontType or SYMBOL_FONTTYPE;
if ALogFont.lfPitchAndFamily = FIXED_PITCH then
AFontType := AFontType or FIXEDPITCH_FONTTYPE;
AFontLoader.FontList.AddObject(AFaceName, TObject(Integer(AFontType)));
end;
if AFontLoader.Terminated then
Result := 0
else
Result := 1;
end;
function EnumFontsProc1(var ALogFont: TLogFont;
var ATextMetric: TTextMetric; AFontType: DWORD;
AData: LPARAM): Integer; stdcall;
begin
Result := EnumFontsProc2(TcxFontLoader(AData), ALogFont, AFontType);
end;
---
function QRRTFEnumFontsProc(var LogFont: TLogFont; var TextMetric: TTextMetric;
FontType: Integer; Data: Pointer): Integer; stdcall;
var
S: TStrings;
Temp: string;
Family: integer;
begin
S := TStrings(Data);
Temp := LogFont.lfFaceName;
Family := LogFont.lfPitchAndFamily shr 4;
if (S.Count = 0) or (AnsiCompareText(S[S.Count-1], Temp) <> 0) then
S.AddObject(Temp, TObject(Family));
Result := 1;
end;
---
function EnumFontCharsets(var EnumLogFont: TEnumLogFontEx;
PTextMetric: PNewTextMetricEx; FontType: Integer; Data: LPARAM): Integer;
export; stdcall;
var s: String;
l,cs: Integer;
begin
Result := 1;
cs := EnumLogFont.elfLogFont.lfCharSet;
if cs<>MAC_CHARSET then begin
l := StrLen(EnumLogFont.elfScript);
SetLength(s,l);
Move(EnumLogFont.elfScript, PChar(s)^, l);
for l := 0 to TRVFontCharsetComboBox(Data).Items.Count-1 do begin
if Integer(TRVFontCharsetComboBox(Data).Items.Objects[l])=cs then
exit;
if AnsiCompareText(TRVFontCharsetComboBox(Data).Items[l],s)>0 then begin
TRVFontCharsetComboBox(Data).Items.InsertObject(l,s,TObject(cs));
exit;
end;
end;
TRVFontCharsetComboBox(Data).Items.AddObject(s, TObject(cs));
end;
end;
---
function EnumFontsProc(var ALogFont: TLogFont; var ATextMetric: TTextMetric;
AFontType: DWORD; AData: LPARAM): Integer; stdcall;
begin
if ALogFont.lfCharSet = SYMBOL_CHARSET then
AFontType := AFontType or SYMBOL_FONTTYPE;
if ALogFont.lfPitchAndFamily = FIXED_PITCH then
AFontType := AFontType or FIXEDPITCH_FONTTYPE;
FFontList.AddObject(ALogFont.lfFaceName, TObject(Integer(AFontType)));
Result := 0;
end;
---
Сдается мне, что15.07.08 20:36 Автор: Neznaika <Alex> Статус: Member Отредактировано 15.07.08 21:30 Количество правок: 2
1) EnumFontsProc2 - не обьявлена как stdcall. Причем на входе - не 4 параметра, а только 3.
Это фатальная ошибка.
И в добавок, многопоточность - неправильно реализована. Поэтому в синий экран и падает.
2) EnumFontCharsets - обьявлена как export.
Не фатально, но "export" надо выкинуть.
3) Ни в одной из функций - не вижу проверки входных параметров.
Для функций обратного вызова - это обязательно.
Ды вроде хелпы говорят не так...16.07.08 09:49 Автор: Ustin <Ustin> Статус: Elderman
> 1) EnumFontsProc2 - не обьявлена как stdcall. Причем на > входе - не 4 параметра, а только 3. > Это фатальная ошибка. > И в добавок, многопоточность - неправильно реализована. > Поэтому в синий экран и падает. EnumFontsProc2 - всего лишь вызывается из callback, такая запись - обычная практика в delphi
За многопоточность - не могу понять где ошибка...
> 2) EnumFontCharsets - обьявлена как export. > Не фатально, но "export" надо выкинуть. The directives near, far, and export refer to calling conventions in 16-bit Windows programming. They have no effect in Win32, or in .NET applications and are maintained for backward compatibility only
> 3) Ни в одной из функций - не вижу проверки входных > параметров. > Для функций обратного вызова - это обязательно. Эмм... проверки на что? Логика вроде как именно на них и базируется :)
Насчет того, что баг - в винде, это ты пожалуй, загнул слегка16.07.08 19:19 Автор: Neznaika <Alex> Статус: Member
1) EnumFontsProc2:
Для правильной реализации многопоточности - надо использовать блокировки.
Блокировки чаще всего делаются через EnterCriticalSection/LeaveCriticalSection
2) EnumFontCharsets:
Правильно, export - только для обратной совместимости. И поэтому его надо выкинуть.
Что будет, если одновременно ставить export и stdcall -- никто в компаниии Borland не проверял.
3) Про проверку входных параметров:
Это когда один из параметров описан как "Data: Pointer". И он всегда может быть нулевым.
А ты без проверки - делаешь S := TStrings(Data);