-
Notifications
You must be signed in to change notification settings - Fork 0
/
longjmp.c
68 lines (50 loc) · 1.9 KB
/
longjmp.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void first();
static void second();
/* Use a file scoped static variable for the exception stack so we can access
* it anywhere within this translation unit. */
static jmp_buf exception_env;
static int exception_type;
int main(void) {
char* volatile mem_buffer = NULL;
if (setjmp(exception_env)) {
// if we get here there was an exception
printf("first failed, exception type: %d\n", exception_type);
} else {
// Run code that may signal failure via longjmp.
puts("calling first");
first();
mem_buffer = malloc(300); // allocate a resource
printf("%s\n", strcpy(mem_buffer, "first succeeded")); // not reached
}
free(mem_buffer); // NULL can be passed to free, no operation is performed
return 0;
}
static void first() {
jmp_buf my_env;
puts("entering first"); // reached
memcpy(my_env, exception_env, sizeof my_env);
switch (setjmp(exception_env)) {
case 3: // if we get here there was an exception.
puts("second failed, exception type: 3; remapping to type 1");
exception_type = 1;
default: // fall through
memcpy(exception_env, my_env, sizeof exception_env); // restore exception stack
longjmp(exception_env, exception_type); // continue handling the exception
case 0: // normal, desired operation
puts("calling second"); // reached
second();
puts("second succeeded"); // not reached
}
memcpy(exception_env, my_env, sizeof exception_env); // restore exception stack
puts("leaving first"); // never reached
}
static void second() {
puts("entering second" ); // reached
exception_type = 3;
longjmp(exception_env, exception_type); // declare that the program has failed
puts("leaving second"); // not reached
}