15 213 Recitation 7 31802 Outline fork and
- Slides: 23
15 -213 Recitation 7 – 3/18/02 Outline • fork and scheduling • Signals • setjmp/longjmp – Emulating C++ exceptions in C James Wilson e-mail: wilson 2@andrew. cmu. edu Office Hours: Friday 1: 30 – 3: 00 Wean Cluster 520 x
What output does the following have? int main(int argc, char *argv[]) { int i = 0; else { printf("%dn", i); } return 0; printf("%dn", i); if(fork()) { ++i; printf("%dn", i); } else { printf("%dn", i); } } }
Scheduling Dependent Output • Parents always first produces: – 0, 1, 2, 0, 1 • Lowest level child always first: – 0, 0, 1, 1, 2 • A good number more versions…
What’s wrong with the code? int main(int argc, char *argv[]) { int i = 0; else { printf("%dn", i); } return 0; printf("%dn", i); if(fork()) { ++i; printf("%dn", i); } else { printf("%dn", i); } } }
Need to add wait() int main(int argc, char *argv[]) { int i = 0; else { printf("%dn", i); } return 0; printf("%dn", i); if(fork()) { ++i; printf("%dn", i); wait(); } else { printf("%dn", i); } wait(); } }
Signals • Software events generated by OS and processes – an OS abstraction for exceptions and interrupts • Sent from the kernel or a process to other processes. • Different signals are identified by small integer ID’s • Only information in a signal is its ID and the fact that it arrived. Num. Name 2 SIGINT Default Description Terminate Interrupt from keyboard (cntl-c) Terminate Kill program (cannot override or ignore) 11 SIGSEGV Terminate & Dump Segmentation violation 14 SIGALRM 17 SIGCHLD Terminate Timer signal Ignore Child stopped or terminated 9 SIGKILL
Signals #include <stdio. h> #include <malloc. h> #include <signal. h> // Signal handler // Called when process receives signal // Just exits static void sig_handler ( int sig ) { printf( "Segmentation fault caught, exiting gracefully. n" ); exit ( 16 ); }
Signals int main() { float *f, t 1, t 2; signal ( SIGSEGV, sig_handler ); // set function to handle signals f = (float*) malloc ( 3 * sizeof ( float ) ); f[0] = 1; f[1] = 8; f[2] = 7; t 1 = *(f+0) + *(f+1); printf ( "%fn", t 1 ); } free ( f ); f = NULL; // set f to NULL t 2 = *(f+1) + *(f+2); printf ( "%f", t 2 ); return 0; // accessing it generates SIGSEGV // which is caught by process and // and calls handling function
Signals • Output without signal handling: • %. /signal • 9. 000000 • Segmentation fault • Output with signal handling: • %. /signal • 9. 000000 • Segmentation fault caught, exiting gracefully. • Provides programmer with method to clean up program (free all used blocks of memory, unlock mutex, etc. . ) if a kill signal is sent
Setjmp, Longjmp int setjmp(jmp_buf env); void longjmp(jmp_buf env, int val); Useful functions for dealing with errors and interrupts • setjmp saves its environment (i. e. registers) in env for later use by longjmp • After longjmp completes, program starts after call to setjmp, as if setjmp had returned val.
Setjmp, Longjmp: Example What is the output of the following program? #include <setjmp. h> #include <stdio. h> int a(char *s, jmp_buf env) { int i; i = setjmp(env); printf("Setjmp returned -- %dn", i); printf("s = %sn", s); int main() { jmp_buf env; if(a("Bob", env) != 0) exit(0); b(3, env); return i; } int b(int i, jmp_buf env) { printf("In b: i = %d, Calling longjmpn", i); longjmp(env, i); } return 0; }
Setjmp, Longjmp: Example con’t UNIX> sj Setjmp returned -- 0 s = Bob In b: I = 3, Calling longjmp Setjmp returned -- 3 s = Bob UNIX> sj Setjmp returned -- 0 s = Bob In b: I = 3, Calling longjmp Setjmp returned -- 3 Segmentation Fault
Setjmp, Longjmp: Example con’t Let’s take a look at the stack to see why we’re segfaulting. %ebp old %ebp First, main( ) looks like this. env[8]. . . env[0] %esp %eip --> in main
Setjmp, Longjmp: Example con’t old %ebp env[8]. . . Then main( ) calls a( ). env[0] s = “Bob” Rtn Addr %ebp old %ebp i %esp %eip --> in a
Setjmp, Longjmp: Example con’t old %ebp env[8] Then main( ) calls a( ). …. env[0] s = “Bob” Rtn Addr %ebp old %ebp i %esp %eip --> in a Then a( ) calls setjmp( ). This saves the current state of the registers.
Setjmp, Longjmp: Example con’t old %ebp env[8] …. env[0] Returned to main( ), and main( ) calls b( ). i = 3 Rtn Addr %ebp old %ebp %esp i %eip --> in b
Setjmp, Longjmp: Example con’t old %ebp env[8] …. env[0] s =? ? 3 longjmp( ) is called, and the regs are restored to their values of when a( ) was called. Rtn Addr %ebp old %ebp %esp i %eip --> in a Why the segfault? ? --> the stack is in a bad state. a( ) expects a (char *) instead of the int value 3. This a common bug with setjmp/longjmp ---> You CANNOT return from a function that calls setjmp!
C++ exception handling introduction • A more general and powerful error handling mechanism than return values • Simplified syntax: class A { }; try { do_something(); } catch (const A&) { // handle exception A } • The function do_something can throw/raise exceptions with: throw A();
C++ exception handling introduction • Exceptions can be arbitrary types in C++, including objects with constructors • C++ allows for nested try blocks; exceptions that are uncaught at one level percolate up to the next – Uncaught exceptions terminate the program, but this behavior can be changed • The full syntax and semantics, like most of C++, is complicated – Read Stroustrup, chapter 14
Emulating exception handling in C • setjmp/longjmp mechanism allows for some limited emulation of C++ exceptions • Use setjmp to set up a try block and the exception handlers • Exceptions are thrown using longjmp with an appropriate exception code
C++ exception handling example #include <stdio. h> #include <math. h> #include <unistd. h> class Range { }; class Close { }; void sqrt_loop(void) { double d; printf("Enter a number between 0 and 100: "); if (scanf("%lf", &d) == EOF) throw Close(); if (d<0 || d>100) throw Range(); printf("Square root of %f is %fn", d, sqrt(d)); } int main(void) { try { while(1) sqrt_loop(); } catch (const Range &) { fprintf(stderr, "Number out of rangen"); exit(0); } catch (. . . ) { fprintf(stderr, "Uncaught exceptionn"); exit(1); } return 0; }
Emulating exception handling in C example #include <setjmp. h> <stdio. h> <math. h> <unistd. h> int main(void) { int ex_no; switch (ex_no = setjmp(ex_buf)) { case 0: while(1) sqrt_loop(); break; case EX_RANGE: fprintf(stderr, "Number out of rangen"); exit(0); default: fprintf(stderr, "Uncaught exception %dn", ex_no); exit(ex_no); } return 0; jmp_buf ex_buf; #define EX_RANGE 1 #define EX_CLOSE 2 void sqrt_loop(void) { double d; printf("Enter a number between 0 and 100: "); if (scanf("%lf", &d) == EOF) longjmp(ex_buf, EX_CLOSE); if (d<0 || d>100) longjmp(ex_buf, EX_RANGE); printf("Square root of %f is %fn", d, sqrt(d)); } }
Limitations • We can only throw an integer error code to the exception catcher. C++ allows arbitrary objects to be thrown – You can create a pointer for an “exception object, ” but this is not type-safe and allocation/disposal is not automatic • Need a stack of jmp_buf structures to emulate an exception stack – Otherwise, storing and restoring the exception jmp_buf gets messy – Uncaught exceptions are not automatically rethrown • Even with a stack, the above implementation is not thread-safe – Each thread needs a separate exception stack
- Sigchild
- Outline 213
- Outline 213
- Outline 213
- Active recitation
- Quood recitation
- Rote recitation of a written message
- Learning objectives for poem
- Reciting a poem
- What is meant by etiquette of recitation of the holy quran
- Xvvvxv
- Product-oriented rubric sample
- Rcitation
- Citation sandwich example
- Uml activity diagram
- Fork exec wait in c
- Se 555
- Marine type connecting rod
- Fork() wait() exec() and exit() system calls
- Connecting rod definition
- 123+132+321+312
- Sbi 213
- Northwestern cs 213
- Cow.ceng.metu.edu tr