Zum Inhalt springen

Empfohlene Beiträge

Geschrieben

Ich habe folgendes Problem :

Ich möchte sichergehen, daß mein Programm beendet wird, wenn ein Thread ein Absturz hatte. In dem Fall möchte ich auch vermeiden, daß das bekannte Fenster erscheint, welches mich über den Absturz informiert. Dazu habe ich ein paar Fragen.

1. Gibt es die Möglichkeit zu erkennen, ob ein Thread stehengeblieben ist, in dem Fall aufgrund des Absturzes ? GetThreadExitCode() reicht noch nicht aus (bleibt bei STILL_ACTIVE).

2. Gibt es eine Methode / Funktion, die die Absturzmeldung übernimmt, welche ich überschreiben kann ?

Die Threads sind sehr komplex und nutzen etliche Objecte. Aus dem Grunde kann es immer passieren, daß ein Absturz stattfindet. Leider ist es zur Zeit so, daß wenn ein Thread abstürzt, alle anderen noch funktionieren, d.h. auch der Timer funktioniert noch, und ich wollte vermeiden für jeden Thread ein Timer mitzugeben (sind recht viele Threads).

Die Threads können auch recht lange dauern, aus dem Grunde ist eine Abfrage nach der Dauer eines Threads auch Schwierig.

Das wärs erstmal,

kind regards,

Kristian Kratzenstein

Geschrieben

Im ersten Augenblick völlig richtig. Aber im zweiten :

Ich habe ein recht komplexes Project. Eine absolute Fehlerfreiheit herzustellen ist zwar ein ideal, aber das kann ich nicht erreichen. (wer kann das schon).

Es soll kein mir bekannter Fehler abgefangen werden, sondern ein mir unbekannter (da ich die bekannten ja behebe).

Ich habe eine SelfDebugging Klasse geschrieben, welche bisher sauber funktioniert, nur brauch diese die Information zum debuggen, welches natürlich erst passieren soll, wenn ein Thread einen Absturz hingelegt hat.

Es gibt recht viele Absturzmöglichkeiten, zZt teste ich mit einem selbsterzeugten "written" auf "0x00000000" (da weiß ich genau wo der ist, is ja Absicht).

kind regards,

Kristian Kratzenstein

Geschrieben

try und catch habe ich auch schon getestet. Aber anscheinend muß dies im kleinen Maßstab gemacht werden. Das ist bei den Mengen an Objecten etwas schwierig (ich habs mal grob probiert, aber er kommt in die exception nicht hinein. Grob heißt um das Aufrufen der Hauptmethode im Hauptobject, welches von der Threadfunktion aufgerufen wird habe ich mit try umklammert).

Aus dem Grunde suche ich ja nach Grundsätzlichen Positionen / Funktionen / Methoden und oder Informationen, um diesen Absturz abzufangen. Es würde mir schon reichen, wenn ich jede 5 sec einen Thread abfragen kann, ob dieser schon abgestützt ist (ohne jetzt die CWinThread grob ändern zu müssen).

Codeproject hat mir bei einigen Dingen geholfen, aber zu dem Thema habe ich leider noch nichts gefunden. (is leider nicht alles enthalten)

kind regards,

Kristian Kratzenstein

Geschrieben

"Funktioniert nicht" ;)

Also, ich hab das nun mal getestet. Da ein wenig mehr Arbeit nötig, damit ich mit die Handles der Threads behalte (bisher waren die nicht wichtig). Aber die Funktion "WaitForSingleObject" gibt immer einen Timeout zurück (oder WAIT_FAILT, wenn der Thread zZt nicht läuft, dann immer mit Error 6).

die translator geschichte hilf hierbei leider nicht, auch die "set_terminate", in welche ich kurzfristig Hoffnung steckte greift hierbei nicht.

Da ich jetzt die Klasse CWinThread (bzw einen Erben) direkt benutze, ohne AfxBeginThread, können Ideen auch direkt dort eingebettet werden.

Wenn es geht würde ich auf das try catch verzichten, außer jemand hat eine Idee, wie ich dies sehr Grob machen kann.

kind regards,

Kristian Kratzenstein

Geschrieben
Aber die Funktion "WaitForSingleObject" gibt immer einen Timeout zurück (oder WAIT_FAILT, wenn der Thread zZt nicht läuft, dann immer mit Error 6).

Timeout ist ja in Ordnung -> Thread wird ausgeführt. Aber was meinst du mit "läuft zZt nicht"? 6 ist ERROR_INVALID_HANDLE.

Geschrieben

Ich habe CWinThread Objekte (bzw Erben). Diese werden gestartet, und beendet, aber nicht zerstört, Dadurch habe ich einen invalid Handle, wenn der Thread nicht läuft (d.H läuft zZt nicht).

Sprich : Die Meldungen sind mir bekannt, und habe auch keinen Fehler in diesen gesehen.

kind regards,

Kristian Kratzenstein

Geschrieben
Ich habe CWinThread Objekte (bzw Erben). Diese werden gestartet, und beendet, aber nicht zerstört, Dadurch habe ich einen invalid Handle, wenn der Thread nicht läuft (d.H läuft zZt nicht).
Ich verstehe immer noch nicht, was du mit "läuft zZt nicht" meinst. Das Handle eines Threads wird erst dann ungültig, wenn jemand CloseHandle aufruft. Das passiert AFAIK bei einem erfolgreich erstellten CWinThread nur im Destruktor. Wenn also die Objekte nicht zerstört werden, solltest du nicht ERROR_INVALID_HANDLE bekommen.
Geschrieben

Das ist nicht richtig. Der Handle wird zerstört, wenn Delete aufgerufen wird, und dies ist nicht nur im Destruktor der Fall. Es gibt einen Zusatz "m_hAutoDelete". Wenn dieser False ist, wird das Objekt nicht zerstört, wenn der Thread beendet wird. Der Handle ist dann ungültig (da kein Thread mehr läuft) aber das Objekt ist noch da. Dadurch brauche ich den Thread nur einmal zu initialisieren, und kann ihn dann immer wieder starten und beenden.

kind regards,

Kristian Kratzenstein

Geschrieben
Das ist nicht richtig. Der Handle wird zerstört, wenn Delete aufgerufen wird, und dies ist nicht nur im Destruktor der Fall. Es gibt einen Zusatz "m_hAutoDelete". Wenn dieser False ist, wird das Objekt nicht zerstört, wenn der Thread beendet wird.
CWinThread::Delete "zerstört" kein Handle. Es gibt auch keinen Aufruf von CloseHandle in CWinThread::Delete. Delete ruft den Destruktor auf, falls m_bAutoDelete true ist, mehr nicht. Der ruft CloseHandle auf.

Der Handle ist dann ungültig (da kein Thread mehr läuft) aber das Objekt ist noch da.
Ein Threadhandle wird nicht ungültig, wenn der zugehörige Thread terminiert. Das passiert erst bei CloseHandle (im Destruktor von CWinThread).

Dadurch brauche ich den Thread nur einmal zu initialisieren, und kann ihn dann immer wieder starten und beenden.
Davon rate ich dringend ab. Du solltest für einen neuen Thread auch eine neue CWinThread-Instanz anlegen. Ich könnte mir vorstellen, dass es zu Initialisierungs- oder Deinitialiserungsproblemen kommt, wenn du dieselbe Instanz wiederverwendest.
Geschrieben

Eigendlich dem Thema nicht besonders förderlich. Aber ein paar Punkte, durch welche ich diese Art und Weise als richtig erkenne :

afxwin.h :

ca. Line 4040

// only valid while running

HANDLE m_hThread; // this thread's HANDLE

operator HANDLE() const;

DWORD m_nThreadID; // this thread's ID

4085:

virtual void Delete();

// 'delete this' only if m_bAutoDelete == TRUE

MSDN (CWinThread class (MFC)) (Vorletzter Absatz):

Instead of calling AfxBeginThread, you can construct a CWinThread-derived object and then call CreateThread. This two-stage construction method is useful if you want to reuse the CWinThread object between successive creation and terminations of thread executions.

Hoffendlich ist dies dadurch geklärt.

kind regards,

Kristian Kratzenstein

Geschrieben

Gut, das Wiederverwenden ist wohl in Ordnung. Aber bekommst du hier WAIT_FAILED?

#include <afx.h>
#include <afxwin.h>

CWinApp theApp;

UINT Thread(LPVOID)
{
return 0;
}

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0);

CWinThread t(Thread, 0);
t.m_bAutoDelete = FALSE;
t.CreateThread();

Sleep(2000);

DWORD res = WaitForSingleObject(t.m_hThread, 0);
}[/CODE]

Geschrieben

Tatsächlich. Ich bekomme dabei WAIT_OBJECT_0. (Anscheinend möchte er melden, daß er beendet ist). dH Handle ist aktiv. Nur Frage ich mich wieso (und wozu), da der Thread garnicht mehr exisitert (und in der Inlinedokumentation anders beschrieben wird).

Nun kann ich ja nicht CloseHandle in Delete hinzufügen, da sonst zweimal versucht wird dies zu schließen, wenn die Klasse beendet wird. (Der Handle war eigendlich dazu gedacht, zu sehen, ob der Thread noch läuft.. da hatte ich wohl nen kleinen Fehler eingebaut). Na, da muß ich wohl doch mehr änderungen einbauen *grummel*.

So, hast du eine andere Idee, wie wir dem Crash auf die Spur kommen ?

Leider sprint er auch nicht in die

virtual LRESULT ProcessWndProcException(CException* e, const MSG* pMsg)

, welche ich einfach mal überschrieben habe.

kind regards,

Kristian Kratzenstein

Geschrieben
Tatsächlich. Ich bekomme dabei WAIT_OBJECT_0. (Anscheinend möchte er melden, daß er beendet ist). dH Handle ist aktiv. Nur Frage ich mich wieso (und wozu), da der Thread garnicht mehr exisitert (und in der Inlinedokumentation anders beschrieben wird).
WAIT_OBJECT_0 bedeutet, dass der Thread beendet ist. Läuft er noch, bekommst du WAIT_TIMEOUT. Kannst du das nicht nutzen?

So, hast du eine andere Idee, wie wir dem Crash auf die Spur kommen ?

Leider sprint er auch nicht in die

virtual LRESULT ProcessWndProcException(CException* e, const MSG* pMsg)

, welche ich einfach mal überschrieben habe.

Ich hab da noch ein paar Sachen im Hinterkopf, habe aber gerade nicht die Zeit, sie rauszusuchen. Ich melde mich nochmal. Kannst du den abzufangenden Crash genauer spezifizieren?
Geschrieben

Leider kann ich das nicht nutzen (kann nicht sagen wie lange ein Thread dauern kann, da diese auch mehrere Jobs in Reihe bearbeiten können).

Den crash könnte ich nennen (meinen Testcrash :

char * buffer = NULL;

while(1){ buffer[i++] = 0;}

Aber eigendlich will ich Abstürze allgemein abfangen, also ohne daß ich weiß was für eine Art dieser ist. Dazu ja das Selfdebugging.

kind regards,

Kristian Kratzenstein

PS : Vielen Dank für deine bisherige Hilfe.

Geschrieben

Anmerkung: Erfordert Compileroption /EHa

#include <afx.h>
#include <afxwin.h>
#include <eh.h>

CWinApp theApp;

typedef void (*_se_translator_function)(unsigned int, struct _EXCEPTION_POINTERS* );

class E
{
};

void SeTranslator(unsigned int n, struct _EXCEPTION_POINTERS* p)
{
throw E();
}

UINT Thread(LPVOID)
{
_se_translator_function old = _set_se_translator(SeTranslator);
try
{
int* p(0);
*p = 42;
}
catch(E e)
{
AfxMessageBox("Caught");
}
_set_se_translator(old);
return 0;
}

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0);

CWinThread t(Thread, 0);
t.m_bAutoDelete = FALSE;
t.CreateThread();

Sleep(2000);

DWORD res = WaitForSingleObject(t.m_hThread, 0);
}
[/CODE]

Aus _EXCEPTION_POINTERS* p solltest du einiges an Informationen rausholen können.

Geschrieben

Vielen Dank, das scheint wirklich zu funktionieren. Damit gebe ich dir nachträglich recht und schäme mich schwarz *g*.

Weiß nicht wieso ich mich so gegen try und catch gewehrt habe.. so jetzt nachträglich gesehen. Der Fehler taucht in der ... 5 oder 6 Ebene auf (UnterObjekte), und trotzdem wird dies hier abgeleitet.

Thanks a lot.

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...