errors and exception handling tim bisson. outline for today kernel development debugging, error...
TRANSCRIPT
Errors and Exception Handling
Tim Bisson
Outline for Today
Kernel Development Debugging, error handling, and virtual machines
Userspace C 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 Run on live system
Serial Debugging 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 Just reboot the virtual machines (like restarting an app)
Speeds up kernel development 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 open-source kernel development
Contribute to an open source kernel project: Linux, FreeBSD, NetBSD, DragonFlyBSD “Microsoft isn't evil, they just make really crappy operating
systems.” - Linus Torvalds
Tons of cool projects to work on 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
Debugger can trace the error to source (gdb) Kernel faults can often be fatal for the whole system
Drivers are typically responsible for OS failures 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#define SIZE 10
int main() { char buf[SIZE]; int ret, fd;
ret = read(fd,buf, SIZE); if (ret != SIZE) { perror("Read Error"); exit(1); } return 0;}
bisson root # gcc this.c && a.outRead Error: Bad file descriptor
Why does the program fail?
Read(2) sets errno value to EBADF
Perror(3) describes EBADF
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