Recitation 7 (Oct. 25) Outline Exceptions Process Signals Non-local jumps Reminders Lab4: Due Thursday Minglong Shao [email protected] Office hours: Thursdays 5-6PM Wean Hall 1315
Download
Report
Transcript Recitation 7 (Oct. 25) Outline Exceptions Process Signals Non-local jumps Reminders Lab4: Due Thursday Minglong Shao [email protected] Office hours: Thursdays 5-6PM Wean Hall 1315
Recitation 7 (Oct. 25)
Outline
Exceptions
Process
Signals
Non-local jumps
Reminders
Lab4:
Due Thursday
Minglong Shao
[email protected]
Office hours:
Thursdays 5-6PM
Wean Hall 1315
Exceptional control flow (ECF)
Abrupt changes in the control flow
React to changes in system state that are not
captured by internal program variables and are
not necessarily related to the execution of the
program
Happens at all levels of a computer system
Exceptions
Concurrent processes
Signals
Non-local jumps
Exceptions
Interrupt (asynchronous exceptions)
I/O interrupt, hardware reset, software reset, etc.
Traps
System calls, breakpoint traps, etc.
Faults
Page fault, protection fault, etc.
Aborts
Parity error, machine check, etc.
Process concept
An instance of running program
Multiple processes run “concurrently” by time
slicing
Context switching
Control flow passes from one process to another
Preemptive scheduler of OS
Process IDs & process groups
A process has its own, unique process ID
pid_t getpid();
A process belongs to exactly one process group
pid_t getpgrp();
A new process belongs to which process group?
Its parent’s process group
A process can make a process group for itself and its
children
pid_t pid = getpid();
setpgid(0, 0);
getpgrp()
Create a new process
int fork(void)
Create a new process that is identical to the
parent process
Return 0 to child process
Return child’s pid to the parent process
Call once, return twice
Test your understanding…
Problem 1
Problem 1
#include <unistd.h>
#include <stdio.h>
int cnt = 0;
int main(void)
{
if (fork() == 0){
cnt ++;
fork();
cnt++;
}
cnt ++;
printf("%d", cnt);
return 0;
}
Possible output:
133
313
331
Reaping child process
Child process becomes zombie when terminates
Still consume system resources
Parent performs reaping on terminated child
pid_t wait(int *status)
pid_t waitpid(pid_t pid, int *status, int
options)
Straightforward for reaping a single child
Tricky for Shell implementation!
Multiple child processes
Both foreground and background
Practice time again: problem 2
Problem 2
int main(){
int status;
int counter = 1;
if (fork() == 0){
counter ++;
printf("%d", counter);
}else {
if (fork() == 0){
printf("9");
counter --;
printf("%d", counter);
exit(0);
}else {
if (wait(&status) > 0){
printf("6");
}
}
}
printf("8");
exit(0);
}
Answers:
A. Y
B. N
C. Y
D. N
E. Y
Signals
Section 8.5 in text
Read at least twice … really!
A signal tells our program that some event has
occurred
Can we use signals to count events?
No
Why? Signals not queued!!
Important signals (Fig 8.23)
SIGINT
Interrupt signal from terminal (ctrl-c)
SIGTSTP
Stop signal from terminal (ctrl-z)
SIGCHLD
A child process has stopped or terminated
Signals: sending
Process 1
Process 2
kill(pid, SIGINT)
1
blocked
pending
OS procedure
• divide by zero:
SIGFPE
• ctrl-c: SIGINT
• child process exit:
SIGCHLD
other events
OS Kernel
Signals: receiving
Check when
schedule the
process to run
Process 2
0
1
blocked
pending
OS procedure
OS Kernel
Receiving a signal
Default action
The process terminates [and dumps core]
The process stops until restarted by a SIGCONT
signal (ctrl-z)
The process ignore the signal
Can modify (additional action)
“Handle the signal” -- install signal handler
void sigint_handler(int sig);
signal(SIGINT, sigint_handler);
An example: problem 3
Problem 3
void handler(int sig){
static int beeps = 0;
printf("YO\n");
if (++beeps < 2)
alarm(1); /* next SIGALRM will be delivered in 1s */
else{
printf("MA\n");
kill(getpid(), SIGKILL);
}
}
int main(){
Signal(SIGALRM, handler);
alarm(1); /* next SIGALRM will be delivered in 1s */
while (1)
;
printf(" is Great!\n");
return 0;
}
1. Output:
YO
YO
MA
2. The program will terminate
Signals not queued
int counter = 0;
void handler(int sig)
{
counter++;
sleep(1);
return;
}
Output:
sent SIGUSR2
sent SIGUSR2
sent SIGUSR2
sent SIGUSR2
sent SIGUSR2
counter = 1
int main()
{
int i;
signal(SIGUSER2, handler);
if (fork() == 0){
for (i = 0; i < 5; i++){
kill(getppid(), SIGUSR2);
printf(“sent SIGUSR2 to parent\n”);
}
exit(0);
}
wait(NULL);
printf(“counter = %d\n”, counter);
exit(0);
}
to
to
to
to
to
parent
parent
parent
parent
parent
Race hazard
A data structure is shared by two pieces of code
that can run concurrently
Different behaviors of program depending upon
how the schedule interleaves the execution of
code.
An example of race hazard
sigchld_handler() {
pid = waitpid(…);
deletejob(pid);
}
eval() {
pid = fork();
if(pid == 0)
{ /* child */
execve(…);
}
/* parent */
/* signal handler may run BEFORE addjob()*/
addjob(…);
}
An okay schedule
time
Shell
Signal Handler
Child
fork()
addjob()
execve()
exit()
sigchld_handler()
deletejobs()
A problematic schedule
time
Shell
Signal Handler
Child
fork()
execve()
exit()
sigchld_handler()
deletejobs()
addjob()
Job added to job list after the signal handler tried to delete it!
Solution: blocking signals
sigchld_handler() {
pid = waitpid(…);
deletejob(pid);
}
eval() {
sigprocmask(SIG_BLOCK, …)
pid = fork();
if(pid == 0)
{ /* child */
sigprocmask(SIG_UNBLOCK, …)
execve(…);
}
/* parent */
/* signal handler might run BEFORE addjob() */
addjob(…);
sigprocmask(SIG_UNBLOCK, …)
}
More details 8.5.6 (page 633)
Non-local jump
int setjmp(jmp_buf env)
Must called before longjmp
Stores current register context, stack pointer, and PC in
the jump buffer env
First called, return 0 if no error
void longjmp(jmp_buf env, int i)
Restores register context from jump buffer env
Jumps back to where previous setjmp is called, behaves
like setjmp just completes. But this time it returns i, not 0
Can only jump to an active context
A function that has been called but not yet
completed
Non-local jump (cont)
int sigsetjmp(jmp_buf env)
Also saves blocked signals
void siglongjmp(jmp_buf env, int i)
Restores blocked signals besides others
Let’s see an example: problem 4
Problem 4
jmp_buf stuff;
jmp_buf more_stuff;
int bar(){
if (setjmp(more_stuff) == 0)
return 3;
else
return 6;
}
int foo(){
char c = getc(stdin);
if (c == 'x')
longjmp(stuff, 42);
else if (c == 'y')
longjmp(more_stuff, 17);
else
return bar();
return -1;
}
int main()
{
int n;
n = setjmp(stuff);
while ((n+=foo())<0)
sleep(1);
printf("%d\n", n);
}
Answer:
1. 3
2. 45
3. 45
4. ?
5. ?
Summary
Process
fork(), waitpid(), execl() (and variant)
Reaping child processes
Signals
signal(), install handler, signals not queued
Non-local jumps
Check man page to understand the system calls
better
man waitpid (fork, signal, …)
Read test book!