This page was last modified 16:16, 23 June 2008.
How to catch a panic
From Forum Nokia Wiki
Yes, a panic. Although panics, by their nature, are uncatchable there is a way to prevent them from severely influencing your program.
First off, why would you do it? What is the use-case? Typically a panic draws attention to a programmatic error that should have already been corrected in the program. It always terminates the program execution and it's on purpose: programs panic from an unrecoverable stage. So why would we want to catch a panic if we were able to do so?
Well, there is at least one special use-case: in a test framework used for automated testing. In a typical unit testing framework, for example, where test suites containing test cases are being performed it's always a nice feature if the execution of tests doesn't get interrupted even in case of a fatal error. If the severe programming error doesn't harm other test cases, then it's ideal if the termination of a test case doesn't influence the life-time of other test cases.
Can panics be caught? At first sight, it may seem that User::SetExceptionHandler() would do. But it doesn't: exceptions are not the same as panics. So installing a new exception handler will not enable us to catch panics, even though it makes it possible to catch a small portion of ALL panics (e.g. an access violation aka KERN-EXE 3).
The ultimate solution is to let your test case run in a new thread. A new thread that you have control over: you create, destroy and most importantly monitor it. You can request notification when this thread dies normally or otherwise via RThread::Logon(). Combined this with RThread::ExitReason(), you can get a clue when and how a thread has exited. Even in case of a panic your main thread will not be affected at all so your - test - framework can continue to run.
The following example shows a console based exe which monitors other thread's death, displaying type and reason:
#ifndef THREADNOTIFIER_H #define THREADNOTIFIER_H #include <e32base.h> class CThreadNotifier : public CActive { public: CThreadNotifier(); ~CThreadNotifier(); void ConstructL(); void IssueRequest(); protected: void RunL(); void DoCancel(); TInt RunError(TInt aError); RUndertaker iUndertaker; TInt iThreadHandle; }; #endif
#include "ThreadNotifier.h" #include <e32cons.h> _LIT(KPanicMsg, "THREAD-NOTIFIER"); LOCAL_D CConsoleBase* console; CThreadNotifier::CThreadNotifier() : CActive(CActive::EPriorityStandard) { CActiveScheduler::Add(this); } void CThreadNotifier::ConstructL() { User::LeaveIfError(iUndertaker.Create()); } CThreadNotifier::~CThreadNotifier() { Cancel(); iUndertaker.Close(); } void CThreadNotifier::IssueRequest() { __ASSERT_ALWAYS(!IsActive(), User::Panic(KPanicMsg, 0)); iUndertaker.Logon(iStatus, iThreadHandle); SetActive(); } void CThreadNotifier::RunL() { if (iStatus == KErrDied) { RThread thread; thread.SetHandle(iThreadHandle); console->Printf(_L("Thread %S (%d) died (Type: %d, reason %d)\n"), &thread.Name(), (int)thread.Id(), thread.ExitType(), thread.ExitReason()); thread.Close(); } IssueRequest(); } void CThreadNotifier::DoCancel() { iUndertaker.LogonCancel(); } TInt CThreadNotifier::RunError(TInt /*aError*/) { return KErrNone; } LOCAL_C void callExampleL() { console = Console::NewL(_L("Thread Notifier"), TSize(KDefaultConsWidth, KDefaultConsHeight)); CleanupStack::PushL(console); CActiveScheduler* scheduler = new(ELeave) CActiveScheduler; CleanupStack::PushL(scheduler); CActiveScheduler::Install(scheduler); CThreadNotifier* notifier = new(ELeave) CThreadNotifier; CleanupStack::PushL(notifier); notifier->ConstructL(); notifier->IssueRequest(); CActiveScheduler::Start(); CleanupStack::PopAndDestroy(3, console); // console, scheduler, notifier } GLDEF_C TInt E32Main() { __UHEAP_MARK; CTrapCleanup* cleanup = CTrapCleanup::New(); TRAPD(error, callExampleL()); __ASSERT_ALWAYS(!error, User::Panic(KPanicMsg, error)); delete cleanup; __UHEAP_MARKEND; return 0; }
| Related Discussions | ||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| does not work CancelAsyncRequest Method. | Tanya | General Symbian C++ | 9 | 2007-12-03 06:14 |
| How can I catch the exception of .c in Symbian | xmnlk | General Symbian C++ | 2 | 2008-06-03 04:38 |
| panic USER-EXEC 3 | jmatulja | General Symbian C++ | 7 | 2003-11-21 09:23 |
| OverwritecolorL is crashing in S60 | gigglie | General Symbian C++ | 5 | 2008-04-01 02:54 |
| Nokia Screen lock-up | sgreid101 | Mobile Java General | 2 | 2006-11-22 15:00 |
