Exceptions-signals
Exceptions-signals
1 2
3 4
Carnegie Mellon Carnegie Mellon
Programming challenge
Understanding the nonstandard semantics of the functions
Grandchild Grandchild
Avoiding improper use of system resources
E.g. “Fork bombs” can disable a system
5 6
if (!bg) { /* parent waits for fg job to terminate */ if (!bg) { /* parent waits for fg job to terminate */
int status; int status;
if (waitpid(pid, &status, 0) < 0) if (waitpid(pid, &status, 0) < 0)
unix_error("waitfg: waitpid error"); unix_error("waitfg: waitpid error");
} }
else /* otherwise, don’t wait for bg job */ else /* otherwise, don’t wait for bg job */
printf("%d %s", pid, cmdline); printf("%d %s", pid, cmdline);
} }
} }
9 10
if (!bg) { /* parent waits for fg job to terminate */ if (!bg) { /* parent waits for fg job to terminate */
int status; int status;
if (waitpid(pid, &status, 0) < 0) if (waitpid(pid, &status, 0) < 0)
unix_error("waitfg: waitpid error"); unix_error("waitfg: waitpid error");
} }
else /* otherwise, don’t wait for bg job */ else /* otherwise, don’t wait for bg job */
printf("%d %s", pid, cmdline); printf("%d %s", pid, cmdline);
} }
} }
11 12
Carnegie Mellon Carnegie Mellon
15 16
Carnegie Mellon Carnegie Mellon
Today Signals
Multitasking, shells A signal is a small message that notifies a process that an
event of some type has occurred in the system
Signals
akin to exceptions and interrupts
Nonlocal jumps 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
17 18
Kernel sends a signal for one of the following reasons: Three possible ways to react:
Kernel has detected a system event such as divide‐by‐zero (SIGFPE) or Ignore the signal (do nothing)
the termination of a child process (SIGCHLD) Terminate the process (with optional core dump)
Another process has invoked the kill system call to explicitly request Catch the signal by executing a user‐level function called signal handler
the kernel to send a signal to the destination process
Akin to a hardware exception handler being called in response to an
asynchronous interrupt
19 20
Carnegie Mellon Carnegie Mellon
A process can block the receipt of certain signals blocked: represents the set of blocked signals
Blocked signals can be delivered, but will not be received until the signal Can be set and cleared by using the sigprocmask function
is unblocked
No Counting!!!
21 22
linux> ps
Examples PID TTY TIME CMD
pid=20 Fore‐ Back‐ Back‐ /bin/kill –9 24818 24788 pts/2 00:00:00 tcsh
pid=32 pid=40 24818 pts/2 00:00:02 forks
pgid=20 ground ground pgid=32 ground pgid=40 Send SIGKILL to process 24818 24819 pts/2 00:00:02 forks
job job #1 job #2
24820 pts/2 00:00:00 ps
Background Background /bin/kill –9 –24817 linux> /bin/kill -9 -24817
linux> ps
process group 32 process group 40 Send SIGKILL to every process
Child Child PID TTY TIME CMD
in process group 24817 24788 pts/2 00:00:00 tcsh
pid=21 pid=22 getpgrp() 24823 pts/2 00:00:00 ps
pgid=20 pgid=20 Return process group of current process linux>
Foreground setpgid()
process group 20 Change process group of a process
23 24
Carnegie Mellon Carnegie Mellon
Foreground
process group 20
25 26
Sending Signals with kill Function Sending Signals with kill Function
void fork12() void fork12()
{ {
pid_t pid[N]; pid_t pid[N];
int i, child_status; int i, child_status;
for (i = 0; i < N; i++) for (i = 0; i < N; i++)
if ((pid[i] = fork()) == 0) if ((pid[i] = fork()) == 0)
while(1); /* Child infinite loop */ while(1); /* Child infinite loop */
/* Parent terminates the child processes */ /* Parent terminates the child processes */
for (i = 0; i < N; i++) { for (i = 0; i < N; i++) {
printf("Killing process %d\n", pid[i]); printf("Killing process %d\n", pid[i]);
kill(pid[i], SIGINT); kill(pid[i], SIGINT);
} }
27 28
Carnegie Mellon Carnegie Mellon
Sending Signals with kill Function Sending Signals with kill Function
void fork12() void fork12()
{ {
pid_t pid[N]; pid_t pid[N];
int i, child_status; int i, child_status;
for (i = 0; i < N; i++) for (i = 0; i < N; i++)
if ((pid[i] = fork()) == 0) if ((pid[i] = fork()) == 0)
while(1); /* Child infinite loop */ while(1); /* Child infinite loop */
/* Parent terminates the child processes */ /* Parent terminates the child processes */
for (i = 0; i < N; i++) { for (i = 0; i < N; i++) {
printf("Killing process %d\n", pid[i]); printf("Killing process %d\n", pid[i]);
kill(pid[i], SIGINT); kill(pid[i], SIGINT);
} }
29 30
Sending Signals with kill Function Sending Signals with kill Function
void fork12() void fork12()
{ {
pid_t pid[N]; pid_t pid[N];
int i, child_status; int i, child_status;
for (i = 0; i < N; i++) for (i = 0; i < N; i++)
if ((pid[i] = fork()) == 0) if ((pid[i] = fork()) == 0)
while(1); /* Child infinite loop */ while(1); /* Child infinite loop */
/* Parent terminates the child processes */ /* Parent terminates the child processes */
for (i = 0; i < N; i++) { for (i = 0; i < N; i++) {
printf("Killing process %d\n", pid[i]); printf("Killing process %d\n", pid[i]);
kill(pid[i], SIGINT); kill(pid[i], SIGINT);
} }
31 32
Carnegie Mellon Carnegie Mellon
Async‐Signal‐Safety Today
Function is async‐signal‐safe if either reentrant (all variables Multitasking, shells
stored on stack frame, CS:APP2e 12.7.2) or non‐interruptible Signals
by signals. Nonlocal jumps
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:
53 54
59 60