Title: Setjmp, Longjmp
1Setjmp, 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.
2Setjmp, Longjmp Example 1
Consider writing a project that will fail if it
ever segfaults. Instead just gracefully restart
it. How would you go about doing this?
Catch the SIGSEGV, and use setjmp/longjmp to jump
back to the beginning.
3Setjmp, Longjmp Example 1 cont
scanf("d", opt) switch(opt) case
1 / FindPerson() / printf("\n
Finding a person\n") break case 2
/ AddPerson() / printf("\n Adding a
person\n") break case 3 /
DeletePerson() / printf("\n Deleting a
person\n") break case 4 exit(0)
default printf("\n Invalid Menu
option\n") break / end while loop
/ return
include ltstdio.hgt int main() int opt
while(1) printf("Directory Main Menu\n")
printf("-------------------------------\n")
printf("1. Find Person\n") printf("2. Add
Person\n") printf("3. Delete Person\n")
printf("4. Exit\n") printf("Enter your menu
option ")
4Setjmp, Longjmp Example 1 cont
include ltsetjmp.hgt include ltsignal.hgt include
ltstdio.hgt jmp_buf Env void handler(int sig)
/ Can do clean up here / longjmp(Env,
1) int main() int opt signal(SIGSEGV,
handler) if(setjmp(Env) ! 0)
printf("\n\n Returning to Main Menu \n")
while(1) printf("Directory Main Menu\n")
printf("-------------------------------\n")
printf("1. Find Person\n") printf("2.
Add Person\n") printf("3. Delete
Person\n") printf("4. Exit\n")
printf("Enter your menu option ")
scanf("d", opt) switch(opt) case 1
/ FindPerson() / printf("\n
Finding a person\n") break case 2
/ AddPerson() / printf("\n Adding a
person\n") break case 3 /
DeletePerson() / printf("\n Deleting a
person\n") break case 4 exit(0)
default printf("\n Invalid Menu
option\n") break / end while loop
/ return
5Setjmp, Longjmp Example 2
What is the output of the following program --
sj.c?
include ltsetjmp.hgt include ltstdio.hgt int
a(char s, jmp_buf env) int i i
setjmp(env) printf("Setjmp returned -- d\n",
i) printf("s s\n", s) return i int
b(int i, jmp_buf env) printf("In b i d,
Calling longjmp\n", i) longjmp(env, i)
int main() jmp_buf env if(a("Bob", env)
! 0) exit(0) b(3,env) return 0
6Setjmp, Longjmp Example 2 cont
Output ???
UNIXgt sj Setjmp returned -- 0 s Bob In b I
3, Calling longjmp Setjmp returned -- 3 s Bob
UNIXgt sj Setjmp returned -- 0 s Bob In b I
3, Calling longjmp Setjmp returned --
3 Segmentation Fault
7Setjmp, Longjmp Example 2 cont
Lets take a look at the stack to see why were
segfaulting.
old ebp
ebp
First, main( ) looks like this. eip --gt in main
env8
.
env0
esp
8Setjmp, Longjmp Example 2 cont
old ebp
env8
Then main( ) calls a( ). eip --gt in a
.
env0
s Bob
Rtn Addr
ebp
old ebp
i
esp
9Setjmp, Longjmp Example 2 cont
old ebp
Then main( ) calls a( ). eip --gt in a Then a(
) calls setjmp( ). This saves the current state
of the registers.
env8
.
env0
s Bob
Rtn Addr
ebp
old ebp
i
esp
10Setjmp, Longjmp Example 2 cont
old ebp
env8
.
Returned to main( ), and main( ) calls b(
). eip --gt in b
env0
i 3
Rtn Addr
ebp
old ebp
i
esp
11Setjmp, Longjmp Example 2 cont
old ebp
env8
longjmp( ) is called, and the regs are restored
to their values of when a( ) was called. eip
--gt in a
.
env0
s ?? 3
Rtn Addr
ebp
old ebp
i
esp
Why the segfault?? --gt the stack is in a bad
state. a( ) expects a (char ) instead of the
int value 3. This a common bug with
setjmp/longjmp ---gt You CANNOT return from a
function that calls setjmp!