Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Symbian OS Explained - Effective C++ Programming For Smartphones (2005) [eng].pdf
Скачиваний:
60
Добавлен:
16.08.2013
Размер:
2.62 Mб
Скачать

15

Panics

We experience moments absolutely free from worry. These brief respites are called panic

Cullen Hightower

One dictionary definition of panic is ”a sudden overpowering fright; sudden unreasoning terror often accompanied by mass flight”. The word panic itself derives from Pan, the Greek god of nature and goatherds, who was half man and half goat. He was considered by some to represent an image of the devil. Panic was said to resemble the mental or emotional state induced by him.

On Symbian OS, when a thread is panicked, the code in it stops running. Panics are used to highlight a programming error in the most noticeable way, stopping the thread to ensure that the code is fixed, rather than potentially causing serious problems by continuing to run. There is no recovery from a panic. Unlike a leave, a panic can’t be trapped. A panic is terminal.

If a panic occurs in the main thread of a process, the entire process in which the thread runs will terminate. If a panic occurs in a secondary thread, it is only that thread which closes. However, on hardware, if any thread is deemed to be a system thread, i.e. essential for the system to run, a panic in the thread will reboot the phone.1 Otherwise, if it’s not a system thread, on target hardware and in release builds on the Windows emulator, the end result of a panic is seen as a ”Program closed” message box, which displays the process name, along with a panic category and error code. In debug emulator builds, you can choose to break into the code to debug the cause of the panic – this is known as just-in-time debugging.

1 Forcing a reboot if a system-critical thread panics is a policy decision rather than a shortcoming of the operating system.

248

PANICS

Panics are used to highlight programming errors by terminating the thread (and, if it is the main thread, the process in which it runs).

15.1Just-In-Time Debugging

On the Windows emulator, in debug builds, you can use the User::SetJustInTime() system function to choose whether a panic kills just the thread or the whole emulator. By default, just-in-time debugging is enabled and a panic will terminate the entire program and enter the debugger. You can disable this by calling User::SetJustInTime(EFalse), whereupon the panic will appear as it does in release builds and simply terminate the thread in which it occurred with an appropriate message box. Just-in-time debugging can be re-enabled by calling User::SetJustInTime(ETrue).

When just-in-time debugging is enabled, the panic calls a function called ThreadPanicBreakPoint(). This function presents the debugger with an information structure which contains information about the ID and name of the thread that panicked, the panic category and reason (which are described shortly), and the name of the thread that caused the panic. The function then breaks into the code and launches the debugger within the context of the function that called the panic, using __asm int 3. You can use the debugger to look through the call stack to see where the panic arose and examine the appropriate state.

There are some subtle differences in behavior between Symbian OS v8.0, which contains the new hard real-time kernel (known at the time of going to press as ”EKA2”, which stands for ”EPOC Kernel Architecture 2”) and previous releases of Symbian OS (EKA1).

Panics on EKA1

A call to the static function User::Panic() panics the currently running thread. A thread may panic any other thread in the system by acquiring an RThread handle to it (as discussed in Chapter 10) and calling RThread::Panic(). Both functions take two parameters: a panic category string, which is limited to 16 characters, and an error code, expressed as a TInt.

Panics on EKA2

A call to the static function User::Panic() panics the currently running thread. A thread may panic any thread in the same process by calling RThread::Panic(), but can no longer panic threads in any other

GOOD PANIC STYLE

249

process.2 The panic functions take a panic category string, which can contain an unlimited number of characters, and an error code, expressed, as usual, as a TInt.

15.2 Good Panic Style

Even without breaking into the debugger, you should still be able to track down the cause of a panic using the panic category string and error number. It’s good style to make your panic category string descriptive and unique, so other developers can locate the string in your header files, and with it, any associated panic error codes (which should also have suitably descriptive names).

Thus, you might have a general panic header file for your library which includes the following:

// ClangerPanic.h

#ifndef __CLANGERPANIC_H__ #define __CLANGERPANIC_H__

#include <e32base.h>

_LIT(KClangerPanic, "CLANGER-ENGINE");

enum TClangerEnginePanic

{

ECorruptBlueStringPudding, // =0, EIronChickenNotInitialized,// =1, EInvalidClangerSetting // =2 };

static void Panic(TClangerEnginePanic aCategory); #endif // __CLANGERPANIC_H__

Which defines the Panic() function separately as follows:

static void Panic(TClangerEnginePanic aCategory)

{

User::Panic(KClangerPanic, aCategory);

}

(You’ll notice by the way that the panic enumeration is a T Class because an enumeration is a type. Chapter 1 discusses the differences between class types on Symbian OS and how to use them.)

When the library code is passed invalid arguments, it may invoke Panic() with the appropriate error code, resulting in a panic and

2 Except where a server thread uses RMessagePtr to panic a misbehaving client thread.

250

PANICS

termination of the thread in which it is running. The category and error will be reported, and may then be traced back by searching the library’s header files for "CLANGER-ENGINE", located inside ClangerPanic.h. You’ll see I’ve commented each error’s enum value with its associated number, just to make the lookup easier. I’ve tried to give each a descriptive name, though obviously they could be further documented, using in-source comments, for clarity.

Of course, if a client programmer has access to the source code for clanger.dll, they can also search it for calls to Panic() which use a particular error value, to track down where a panic originated.

15.3Symbian OS Panic Categories

Symbian OS itself has a series of well-documented panic categories and associated error values. You can find details of platform-specific panics in your preferred SDK. From Symbian OS v7.0, there is a special Panics section in the C++ API Reference of each SDK, which contains a comprehensive list of the Symbian OS system panics. Typical values you may encounter include:

KERN-EXEC 3 – raised by an unhandled exception (such as an access violation caused, for example, by dereferencing NULL, memory misalignment or execution of an invalid instruction) inside a system call to the kernel executive; if an unhandled exception occurs inside code which is instead executing in user mode, the panic is seen as

USER-EXEC 3

E32USER-CBASE 46 – raised by the active scheduler as a result of a stray signal (described further in Chapters 8 and 9)

E32USER-CBASE 90 – raised by the cleanup stack when the object specified to be popped off is not the next object on the stack. The following code illustrates the cause of the panic; this issue is described more fully in Chapter 3, which describes the cleanup stack.

class CExample; // defined elsewhere

void CauseAPanicL()

{

TInt val = 1;

CExample* ptr1 = new (ELeave) CExample();

CleanupStack::PushL(ptr1);

CExample* ptr2 = new (ELeave) CExample();

CleanupStack::PushL(ptr2);

...

CleanupStack::Pop(ptr1); // Panics with E32USER-CBASE 90 here...