Errors and Exception Handling
Download
Report
Transcript Errors and Exception Handling
Errors and Exception
Handling
Tim Bisson
Outline for Today
Kernel Development
Userspace C
Debugging, error handling, and virtual machines
Exception handling?
C++ and Exception handling
Kernel Development
Implement abstract functionality to leverage physical
devices
Optimize physical resources (disk, memory, power)
File Systems can optimize I/O access for mechanical
nature of disks
Debugging/developing OS functionality traditionally
involved pressing the power-switch 100s of times
per day
Very time-consuming
Kernel Debugging
Printk - kernel-level printing
Message classification
KERN_DEBUG, KERN_CRIT, KERN_INFO, …
printk(KERN_CRIT “Bug On\n");
Current process usually faults
Drivers are usually the culprit, so process using that driver
dies
If your lucky, the system won’t panic
Kernel Debugging
KDB
Serial Debugging
Run on live system
Two machines: test and development
Communicate over gdb through serial port
Many systems companies have some form of this
infrastructure
Core dumps
Analyze stack trace off-line
Kernel Development with
Virtual Machines
Virtual machines as test systems - when the break,
they don’t panic the host system
Speeds up kernel development
Just reboot the virtual machines (like restarting an app)
Booting is akin to application start-up
Debugging is easier (run debugger on virtual machine)
Useful for networking, fs, etc development
Parallels, Xen
UML
Run Linux Kernel as a process in Linux
Example using UML
UML uses SIGSEGV to fault pages into the
UML kernel
handle SIGSEGV pass nostop noprint
To ignore such signals when debugging a UML
kernel
Why get involved with opensource kernel development
Contribute to an open source kernel project:
Tons of cool projects to work on
Linux, FreeBSD, NetBSD, DragonFlyBSD
“Microsoft isn't evil, they just make really crappy operating
systems.” - Linus Torvalds
http://www.netbsd.org/contrib/projects.html
http://wiki.dragonflybsd.org/index.cgi/ProjectsPage
Looks really good on your resume…
Apply to SoC ‘07 and get paid to work on an open-source
kernel project for the summer
Kernel Error Handling
A difference between application and kernel programming is
error handling
Application segmentation faults are harmless
Kernel faults can often be fatal for the whole system
Drivers are typically responsible for OS failures
Debugger can trace the error to source (gdb)
They run in kernel address space
Their quality is questionable
Core OS subsystems have error handling too
File System Error Handling
Ext4 - new file system for Linux with many new features
Extents allocation, preallocation, defragmentation, etc…
Sets error code numbers: EIO, ENOMEM, ENOSPC
Some error handlers
Ext4_warning()
Ext4-_error()
Report failure conditions such as inconsistencies or read I/O
failures
Ext4_abort
unrecoverable failures such as journal I/O or ENOMEM
Unconditionally force file system into read-only mode or panic
Ext4_decode_error() - errno values and return string
File System Error Handling (2)
ext4_warning()
ext4_orphan_get() - error handling for bad orphan
inodes
ext4_handle_error()
ext4_get_inode_block() - ensure selected block group
< total block groups
ext4_abort()
ext4_journal_start_sb() - journalling aborted
Goto
Goto is also useful for
aggregating error
handling
Free() is only called from
one place
int function() {
int ret_val = -;
char * data = (char * ) malloc (100);
/* do some work */
if (error) {
ret_val = error1;
goto end;
}
/* do some more work */
if (error) {
ret_val = error;
goto end;
}
end:
/* clean up*/
free (data);
return ret_val;
}
Userland C and exception
handling
C doesn’t support exception handling
It supports supports other functionality
Assert
Goto
Signals
Return/reason codes
System Call/Library Errors
When system call or library errors occur, the
errno variable gets set
Take a look at errno.h (“man errno”) for a list
of possible numbers:
EPERM Operation not permitted (POSIX.1)
EIO Input/output error (POSIX.1)
…
Perror()
Prints a message of describing last error that
occurred
Translates errors into human readable format
Example
Why does the program
fail?
#define SIZE 10
int main() {
char buf[SIZE];
int ret, fd;
Read(2) sets errno
value to EBADF
Perror(3) describes
EBADF
ret = read(fd,buf, SIZE);
if (ret != SIZE) {
perror("Read Error");
exit(1);
}
return 0;
}
bisson root # gcc this.c && a.out
Read Error: Bad file descriptor
Signal Handling
The OS delivers an exception in the form of a
software interrupt to an executing process
process must handle event immediately
Signals are defined by a number
Processes may define signal handlers for a
particular signals
Function called when process receives that signal
Asynchronous execution
What good are signals for
Report errors - invalid memory address
reference
Report asynchronous events
Ctrl-c, ctrl-z, fg
Alternative is event polling
Example - srtgen
A synthetic soft real-time
application generator
Use SIGINT (ctrl-c) to
process current frame,
dump stats, then exit
atexit(3) - register a
function to be called at
normal process
termination
Int bool = 0;
void sig_int (int s) {
fprintf(stderr, “CTRL-C detected, aborting after this
frame\n”);
quit = 1;
}
void dumpstats() {
/*prints application statistics*/
….
}
int main (int argc, char **argv) {
signal (SIGINT, sig_int);
atexit(dumpstats);
do {
…
}while(++numsamples < NUMSAMPLES && !quit);
C++ and Exception Handling
Try-Catch-Throw model
Deals with synchronous and asynchronous errors
Synchronous error example - divide by zero
Put code that may generate an exception in a try
block
try {
//code that might throw an exception
}
Throwing an Exception
Indicates an exception occurred
Specify one operand
Exception object, if operand thrown is an object
Exception caught by closest handler from try block in which
exception thrown
Control transferred to handler
if (denominator == 0)
throw DivideByZeroException();
Exception handler need not terminate program, but block where
exception occurred is terminated
Catching an Exception
Exception handlers are the catch block
Caught if argument type matches throw type
If not, terminate (abort) called
catch (DivideByZeroException ex) {
cout << “Exception occurred: “ << ex.what() << endl;
}
Use catch(…) to catch all exceptions
Simple Example
int main () {
char myarray[10];
try {
for (int n=0; n<=10; n++) {
if (n>9) throw "Out of range";
myarray[n]='z';
}
}
catch (char * str) {
cout << "Exception: " << str << endl;
}
return 0;
}
Re-throwing an Exception
Exception handler can handle some of the
exception, then throw it to the calling function
Uses throw;
void throwException() {
try { // Throw an exception and immediately catch it.
cout << "Function throwException\n";
throw exception();
}
catch( exception e ) {
cout << "Exception handled in function throwException\n";
throw; // re-throw exception for further processing
}
cout << “This should not be print\n”; //control never gets here
}
void main( ) {
try {
throwException();
cout << “This should not be print\n”; //exception will be thrown
}
catch ( exception e ) {
cout << "Exception handled in main" << endl;
}
cout << "Program control continues after catch in main" << endl;
}
Output:
Function throwException
Exception handled in function throwException
Exception handled in main
Program control continues after catch in main