Lecture 13 - Exceptional Control Flow - Signals and Nonlocal Jumps
Lecture 13 - Exceptional Control Flow - Signals and Nonlocal Jumps
1
Carnegie Mellon
2
Carnegie Mellon
Today
Multitasking, shells
Signals
Nonlocal jumps
3
Carnegie Mellon
4
Carnegie Mellon
5
Carnegie Mellon
init [1]
Grandchild Grandchild
6
Carnegie Mellon
Shell Programs
A shell is an application program that runs programs on
behalf of the user.
▪ sh Original Unix shell (Stephen Bourne, AT&T Bell Labs, 1977)
▪ csh BSD Unix C shell (tcsh: enhanced csh at CMU and elsewhere)
▪ bash “Bourne-Again” Shell
while (1) {
/* read */
printf("> ");
Fgets(cmdline, MAXLINE, stdin);
if (feof(stdin))
exit(0);
/* evaluate */
eval(cmdline);
}
}
7
Carnegie Mellon
bg = parseline(cmdline, argv);
if (!builtin_command(argv)) {
if ((pid = Fork()) == 0) { /* child runs user job */
if (execve(argv[0], argv, environ) < 0) {
printf("%s: Command not found.\n", argv[0]);
exit(0);
}
}
9
Carnegie Mellon
10
Carnegie Mellon
11
Carnegie Mellon
Today
Multitasking, shells
Signals
Nonlocal jumps
12
Carnegie Mellon
Signals
A signal is a small message that notifies a process that an
event of some type has occurred in the system
▪ akin to exceptions and interrupts
▪ sent from the kernel (sometimes at the request of another process) to a
process
▪ signal type is identified by small integer ID’s (1-30)
▪ only information in a signal is its ID and the fact that it arrived
13
Carnegie Mellon
Sending a Signal
Kernel sends (delivers) a signal to a destination process by
updating some state in the context of the destination process
14
Carnegie Mellon
Receiving a Signal
A destination process receives a signal when it is forced by
the kernel to react in some way to the delivery of the signal
15
Carnegie Mellon
16
Carnegie Mellon
Signal Concepts
Kernel maintains pending and blocked bit vectors in the
context of each process
▪ pending: represents the set of pending signals
▪ Kernel sets bit k in pending when a signal of type k is delivered
▪ Kernel clears bit k in pending when a signal of type k is received
17
Carnegie Mellon
Process Groups
Every process belongs to exactly one process group
pid=10
pgid=10 Shell
Background Background
process group 32 process group 40
Child Child
18
Carnegie Mellon
linux> ps
Examples PID TTY TIME CMD
▪ /bin/kill –9 24818 24788 pts/2 00:00:00 tcsh
24818 pts/2 00:00:02 forks
Send SIGKILL to process 24818 24819 pts/2 00:00:02 forks
24820 pts/2 00:00:00 ps
linux> /bin/kill -9 -24817
▪ /bin/kill –9 –24817 linux> ps
Send SIGKILL to every process PID TTY TIME CMD
in process group 24817 24788 pts/2 00:00:00 tcsh
24823 pts/2 00:00:00 ps
linux>
19
Carnegie Mellon
Background Background
process group 32 process group 40
Child Child
pid=21 pid=22
pgid=20 pgid=20
Foreground
process group 20
20
Carnegie Mellon
21
Carnegie Mellon
22
Carnegie Mellon
Receiving Signals
Suppose kernel is returning from an exception handler
and is ready to pass control to process p
If (pnb == 0)
▪ Pass control to next instruction in the logical flow for p
Else
▪ Choose least nonzero bit k in pnb and force process p to receive
signal k
▪ The receipt of the signal triggers some action by p
▪ Repeat for all nonzero k in pnb
▪ Pass control to next instruction in logical flow for p
23
Carnegie Mellon
Default Actions
Each signal type has a predefined default action, which is
one of:
▪ The process terminates
▪ The process terminates and dumps core
▪ The process stops until restarted by a SIGCONT signal
▪ The process ignores the signal
24
Carnegie Mellon
Time
27
Carnegie Mellon
kernel code
Inext
user code (main)
28
Carnegie Mellon
31
Carnegie Mellon
33
Carnegie Mellon
Async-Signal-Safety
Function is async-signal-safe if either reentrant (all variables
stored on stack frame, CS:APP2e 12.7.2) or non-interruptible
by signals.
Posix guarantees 117 functions to be async-signal-safe
▪ write is on the list, printf is not
One solution: async-signal-safe wrapper for printf:
Today
Multitasking, shells
Signals
Nonlocal jumps
35
Carnegie Mellon
int setjmp(jmp_buf j)
▪ Must be called before longjmp
▪ Identifies a return site for a subsequent longjmp
▪ Called once, returns one or more times
Implementation:
▪ Remember where you are by storing the current register context,
stack pointer, and PC value in jmp_buf
▪ Return 0
36
Carnegie Mellon
setjmp/longjmp (cont)
void longjmp(jmp_buf j, int i)
▪ Meaning:
▪ return from the setjmp remembered by jump buffer j again ...
▪ … this time returning i instead of 0
▪ Called after setjmp
▪ Called once, but never returns
longjmp Implementation:
▪ Restore register context (stack pointer, base pointer, PC value) from
jump buffer j
▪ Set %eax (the return value) to i
▪ Jump to the location indicated by the PC stored in jump buf j
37
Carnegie Mellon
setjmp/longjmp Example
#include <setjmp.h>
jmp_buf buf;
main() {
if (setjmp(buf) != 0) {
printf("back in main due to an error\n");
else
printf("first time through\n");
p1(); /* p1 calls p2, which calls p3 */
}
...
p3() {
<error checking code>
if (error)
longjmp(buf, 1)
}
38
Carnegie Mellon
P1() P2
{ env
P2(); P3(); At setjmp
}
P2() P1
{
if (setjmp(env)) { env
/* Long Jump to here */ X P2
}
} P2 returns P1
P3() env
{ X P3
longjmp(env, 1);
} At longjmp
40
Carnegie Mellon
while(1) {
sleep(1);
printf("processing...\n");
}
} restart.c
41
Carnegie Mellon
Summary
Signals provide process-level exception handling
▪ Can generate from user programs
▪ Can define effect by declaring signal handler
Some caveats
▪ Very high overhead
▪>10,000 clock cycles
▪ Only use for exceptional conditions
▪ Don’t have queues
▪ Just one bit for each pending signal type
42