Autor Téma: Jak diagnostikovat chybu, když dojde k zamrznutí aplikace?  (Přečteno 467 krát)

Offline age.new

  • Hrdina
  • ****
  • Příspěvků: 358
  • Karma: 0
Vážená skupino,

spravuji jeden rozsáhlý projekt psaný v Delphi 6. Aplikace obsahuje mnoho komponent, komunikuje s externím SW a HW, má databázi, vlastní logování do souborů, canvas kreslení aj.

Bohužel několikrát týdně aplikace zamrzne (přestane odpovídat) a nereaguje. Nepomohla ani kompletní výměna hardware (běží na Windows 7 Embeded). V logu operačního systému je záznam, že aplikace přestala odpovídat. Zkoušel jsem rozšířit logování a zjistit, v jakém případě k tomu dochází, ale bez úspěchu. Aplikace je nasazená u desítek jiných zákazníků, kde k zamrzání nedochází. Vzhledem k rozsáhlosti projektu a rozdílnosti externího SW a HW se na to ale nedá spolehnout a chyba bude pravděpodobně v kódu. Tipoval bych to na obsluhu nějaké události, která se nevrátila ze systému.

Aby to bylo složitější, aplikace je nasazena u zahraničního zákazníka a nemám možnost se k němu připojit. Jsem schopný pouze vygenerovat exe a ten nasadit.

Jak řešíte podobné problémy? Existuje nějaký SW třetí strany, která by dokázala logovat události aplikace? Osobně by mi pomohl výpis zásobníku, ale zamrznutí je náhodné, nedá se nijak předvídat a samozřejmě v momentě zámrzu již nic nezalogujete.

Děkuji za případné rady.


Offline Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 3361
  • Karma: 112
    • Verze Delphi: D2007, DXE + 2 poslední
    • O Delphi v češtině
Re:Jak diagnostikovat chybu, když dojde k zamrznutí aplikace?
« Odpověď #1 kdy: 17-03-2023, 10:49:14 »
Jsou tam vlákna? Nebo je to v podstatě jednovláknová aplikace?
Jelikož je to Delphi 6, používáš výchozí memory manager, nebo je nahrazen? Původní je znám že trpí fraqmentací.
Embarcadero MVP - Czech republic

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 3521
  • Karma: 139
    • Verze Delphi: D2007, XE3, DX10
Re:Jak diagnostikovat chybu, když dojde k zamrznutí aplikace?
« Odpověď #2 kdy: 17-03-2023, 11:56:00 »
Jak řešíte podobné problémy? Existuje nějaký SW třetí strany, která by dokázala logovat události aplikace? Osobně by mi pomohl výpis zásobníku,
Tohle jsme resili detailnim logovanim na ruznych urovnich do ruznych souboru tj. I/O operace spojene s konkretnim zarizenim/protokolem do extra souboru, dumpovani stacku v pripade exception do samostatneho souboru. Pojmenovavali jsme si thready a do logu si psali, co aplikace prave dela a s jakymi hodnotami, detaily byly v tech podruznych souborech. To vsechno ve verzi prelozene v proprietarnim debug rezimu, kde se dala uroven logovani ovladat pres command line. A v produknich verzich zejmena u serverovskych aplikaci jsme to ani vsechno nepovypinali. Ostatne treba SMS centra a podobne servy maji jeste vetsi moznosti, ze mohou v realnem case nastavit filtr a sledovat treba komunikaci s konkretnim mobilem.

No a pak se da pouhym ctenim logu zjistit, co aplikace delala a co delat prestala. Ne, ze by vzdy bylo jasne, co se deje, vetsinou jsme operativne rozsirili logovani a hledali dal.



Offline age.new

  • Hrdina
  • ****
  • Příspěvků: 358
  • Karma: 0
Re:Jak diagnostikovat chybu, když dojde k zamrznutí aplikace?
« Odpověď #3 kdy: 17-03-2023, 12:22:37 »
Je to jednovlánová aplikace a používá FastMM4. Samozřejmě, že některé komunikace s periferiemi mohou probíhat asynchronně. Na mnoha místech je navíc Application.ProcessMessages.

U procedur, které komunikují s perifériemi, jsem rozšířil log. Domníval jsem se, že narazím na místo, které se správně neukončí, resp. zůstane viset. Vždy ale vše doběhlo v pořádku.

Kdyby před zamrznutím došlo k nějaké chybě, tak bych byl schopný s tím něco provést, např. si vytáhnout poslední procedury (něco na způsob zásobníku), ale zamrznutí je náhodné a v ten moment prostě nic nevyexportuji.

Existují nějaké nástroje (komponenty), které jsou schopné "real-time" zápisu zásobníku do souboru? Aby bylo zajištěno, že v moment zamrznutí bude zaznamenána poslední událost na zásobníku? 

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 3521
  • Karma: 139
    • Verze Delphi: D2007, XE3, DX10
Re:Jak diagnostikovat chybu, když dojde k zamrznutí aplikace?
« Odpověď #4 kdy: 17-03-2023, 14:38:21 »
Existují nějaké nástroje (komponenty), které jsou schopné "real-time" zápisu zásobníku do souboru? Aby bylo zajištěno, že v moment zamrznutí bude zaznamenána poslední událost na zásobníku?
Muzes zkusit sledovat pumpu zprav: handler TApplication.OnMessage, v nem dump obsahu TMsg a uvidis, co to udela zejmena s vykonem, jestli si vubec neco takoveho muzes dovolit. To by mohlo leccos napovedet. Teoreticky se dumpovat i ten stack pomoci JclDebug kvuli rekurzi, kdyz volas Application.ProcessMessages.

Kam ta data konkretne strkat a jak s temi informacemi dal nakladat, jestli je treba v OnIdle dumpovat do souboru je otazka, protoze kdyz to zamrzne, tak uz to nemusi byt schopne nic udelat.

Mozna to posilat do jine aplikace, ktera by si udrzovala tail a ktera by nezamrzla, pokud to bude vykonove unosne.

Offline Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 3361
  • Karma: 112
    • Verze Delphi: D2007, DXE + 2 poslední
    • O Delphi v češtině
Re:Jak diagnostikovat chybu, když dojde k zamrznutí aplikace?
« Odpověď #5 kdy: 17-03-2023, 14:39:14 »
Je to jednovlánová aplikace a používá FastMM4. Samozřejmě, že některé komunikace s periferiemi mohou probíhat asynchronně. Na mnoha místech je navíc Application.ProcessMessages.

U procedur, které komunikují s perifériemi, jsem rozšířil log. Domníval jsem se, že narazím na místo, které se správně neukončí, resp. zůstane viset. Vždy ale vše doběhlo v pořádku.

Kdyby před zamrznutím došlo k nějaké chybě, tak bych byl schopný s tím něco provést, např. si vytáhnout poslední procedury (něco na způsob zásobníku), ale zamrznutí je náhodné a v ten moment prostě nic nevyexportuji.

Existují nějaké nástroje (komponenty), které jsou schopné "real-time" zápisu zásobníku do souboru? Aby bylo zajištěno, že v moment zamrznutí bude zaznamenána poslední událost na zásobníku? 


No jakmile je tam Application.ProcessMessage tak je problem asi zde.


Embarcadero MVP - Czech republic

Offline Radek Červinka

  • Administrátoři
  • Padawan
  • *****
  • Příspěvků: 3361
  • Karma: 112
    • Verze Delphi: D2007, DXE + 2 poslední
    • O Delphi v češtině
Re:Jak diagnostikovat chybu, když dojde k zamrznutí aplikace?
« Odpověď #6 kdy: 17-03-2023, 14:41:04 »
Muzes zkusit sledovat pumpu zprav: handler TApplication.OnMessage....

Nebo nahradit ProcessMessage za vlakna se synchronizaci do hlavniho vlakna.
Embarcadero MVP - Czech republic

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 3521
  • Karma: 139
    • Verze Delphi: D2007, XE3, DX10
Re:Jak diagnostikovat chybu, když dojde k zamrznutí aplikace?
« Odpověď #7 kdy: 17-03-2023, 16:41:41 »
Nebo nahradit ProcessMessage za vlakna se synchronizaci do hlavniho vlakna.
Nevim, jestli se jedna o stejnou aplikaci nebo neco jineho, ale pokud si vzpominam, tak ducharinu s uzitim ProcessMessages, dlouhe operace pri kresleni na Canvas, ze mu timeoutovala obsluha pumpy zprav ze strany OS aj. v nejake legacy aplikaci jsme tu s OP resili a k prepsani aplikace ho nepohnuli. Takze to jsem jako moznost uz vynechal a soustredil se jen na to, jak by eventualne  mohl zjistit, co se mu tam deje.

Offline age.new

  • Hrdina
  • ****
  • Příspěvků: 358
  • Karma: 0
Re:Jak diagnostikovat chybu, když dojde k zamrznutí aplikace?
« Odpověď #8 kdy: 20-03-2023, 09:43:03 »
Přepsání kódu na vlákna by bylo možné, ale až budu mít periferie (HW) pro následné důkladné otestování. Domnívám se, že ani to by nebylo nutné, stačilo by komunikaci s HW přespsat do stavového automatu a neřešit nějaké čekání na odpovědi přes Application.ProcessMessages.

Logovat TApplication.OnMessage mě nenapadlo a možná to stojí za zkoušku. Zkusím si i dát kolem těch Application.ProcessMessages nějaké dodatečné logování, abych věděl zda se to zde nějak nezacyklí.

O JclDebug jsem uvažoval, ale implementace mi přijde moc složitá. Jedná se o velký projekt a zas tolik jej rozdrbat nechci. Prakticky se jedná o vyjímku - jeden zákazník ze sta. Ale též se domnívám, že to má spojitost s kreslením na Canvas.

Děkuji za rady.

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 3521
  • Karma: 139
    • Verze Delphi: D2007, XE3, DX10
Re:Jak diagnostikovat chybu, když dojde k zamrznutí aplikace?
« Odpověď #9 kdy: 20-03-2023, 11:05:11 »
O JclDebug jsem uvažoval, ale implementace mi přijde moc složitá. Jedná se o velký projekt a zas tolik jej rozdrbat nechci. Prakticky se jedná o vyjímku - jeden zákazník ze sta. Ale též se domnívám, že to má spojitost s kreslením na Canvas.
To predstavuje jen to prelozit projekt s debug info a na vysledny exe spustit utilitu z JCL makejcldebug.exe a ta na konec .exe pripoji tabulky symbolu a zacatku radku.

Pak zahrnout JCL do projektu, tusim by mely stacit unity JCLDebug, JclHookExcept, JCLShell a nekde v inicializaci aplikace pripojit ten JclDebug k aplikaci:
Kód: Delphi [Vybrat]
  1.     JclAddExceptNotifier(HandleException);
  2.     JclStackTrackingOptions := [stStack,stRawMode,stStaticModuleList];
  3.     JclStartExceptionTracking;
  4.  
a pri finalizaci aplikace do zase odpojit
Kód: Delphi [Vybrat]
  1.     JclStopExceptionTracking;
  2.     JclRemoveExceptNotifier(HandleException);
  3.  
No a pak si obslouzit to HandleException a nekde si udelat stack trace nejak takhle (vlasti stack trace ti udela JclLastExceptStackList.AddToStrings, pomoci GetLocation(Caller(1)) ziskas adresu, kde k ni doslo:
      Info := TStringList.Create;
      try
        JclLastExceptStackList.AddToStrings(Info,FALSE,FALSE,FALSE);
        with GetLocationInfo(Caller(1)) do
          StackLog.LogFmt(eglfiERR,UnitName,ExtractMethodName(ProcedureName),'---------- Stack dump for exception [%s]',[AID]);

        for Idx:=0 to Info.Count-1 do
          StackLog.Log(eglfiERR,sz,sz,Info[Idx]);
        StackLog.Log(eglfiERR,sz,sz,'---------- Bottom of the except stack');
      finally
        Info.Free;
      end;



Offline age.new

  • Hrdina
  • ****
  • Příspěvků: 358
  • Karma: 0
Re:Jak diagnostikovat chybu, když dojde k zamrznutí aplikace?
« Odpověď #10 kdy: 20-03-2023, 11:15:34 »
Takže ten JclAddExceptNotifier(HandleException) se bude volat při změně zásobníku a nebo jen při nějaké expection události? Vzhledem k tomu, že před zamrznutím k žádné vyjímce nedojde, potřeboval bych zásobník logovat nepřetržitě - nejlépe s každou změnou zásobníku.

Děkuji.

Offline pf1957

  • Padawan
  • ******
  • Příspěvků: 3521
  • Karma: 139
    • Verze Delphi: D2007, XE3, DX10
Re:Jak diagnostikovat chybu, když dojde k zamrznutí aplikace?
« Odpověď #11 kdy: 20-03-2023, 13:33:44 »
Takže ten JclAddExceptNotifier(HandleException) se bude volat při změně zásobníku a nebo jen při nějaké expection události?
Ne, to je jen pripojeni handleru k obsluze exception.

Citace
Vzhledem k tomu, že před zamrznutím k žádné vyjímce nedojde, potřeboval bych zásobník logovat nepřetržitě - nejlépe s každou změnou zásobníku.
Jo, na to muzes v podstate kdykoli zavolat nekterou z pretizenych funkci JclCreateStackList viz treba