Lab 9: Signal Handling
Table of Contents
1 Preliminaries
In this lab you will complete a set of C programs that will expose you to the set of system calls that are used in shell pipelines, such as process grouping, pipes, and filed descriptor duplication. There are 2 tasks, and you will likely complete neither of the tasks in lab, You will need to finish the remaining asks outside of the lab period.
1.1 Lab Learning Goals
In this lab, you will learn the following topics and practice C programming skills.
- Using signal handlers,
signal()
andsigaction()
- Scheduling alarm signals with
alarm()
- Using
siginfo_t
when handlingSIGCHLD
1.2 Lab Setup
Run the following command
~aviv/bin/ic221-up
Change into the lab directory
cd ~/ic221/labs/09
All the material you need to complete the lab can be found in the lab directory. All material you will submit, you should place within the lab directory. Throughout this lab, we refer to the lab directory, which you should interpret as the above path.
1.3 Submission Folder
For this lab, all ubmission should be placed in the following folder:
~/ic221/labs/09/
This directory contains 4 sub-directories; examples
, timer
,
term-status
, and mini-sh
. In the examples
directory you will
find any source code in this lab document. All lab work should be
done in the remaining directories.
- Only source files found in the folder will be graded.
- Do not change the names of any source files
Finally, in the top level of the lab directory, you will find a
README
file. You must complete the README
file, and include any
additional details that might be needed to complete this lab.
1.4 Compiling your programs with clang
and make
You are not required to provide your own Makefiles for this lab.
1.5 README
In the top level of the lab directory, you will find a README
file. You must fill out the README file with your name and alpha.
Please include a short summary of each of the tasks and any other
information you want to provide to the instructor.
1.6 Test Script
You are provided a test script which prints pass/fail information
for a set of tests for your programs. Note that passing all the
tests does not mean you will receive a perfect score: other tests
will be performed on your submission. To run the test script,
execute test.sh
from the lab directory.
./test.sh
You can comment out individual tests while working on different parts of the lab. Open up the test script and place comments at the bottom where appropriate.
1.7 Working versions for comparisons
Working versions of all the programs described in this lab document can be found here:
~aviv/lab9-bin/shredder ~aviv/lab9-bin/moresons
Run these programs as a comparison point.
2 PART 1: Shredder: Alarm Management
In this part of the lab you will develop a program that will time
the execution of a child process using alarm()
and signal
handling. Your program will execute a program specified on the
command line and schedule SIGALRM
to occur ever 1
seconds. Dependent on how many alarms are set off, different
information will print to the screen, and if too many alarms are set
off, the program will terminate.
2.1 Task 1 sleep-unroll
For this task, change into the shredder
directory in the lab
directory. In there, you will find the source file shredder.c
.
which you will complete. Your shredder
program most meet the
following specification:
- It must use
alarm()
andSIGALARM
signal handling to count the number of seconds the child process runs. - If the child runs for more than 5 seconds, it must terminate it
with a
SIGKILL
signal. - It must print out different information about the termination state of the child dependent on how long the child ran for.
- It must print "tick-tock" for each
SIGALRM
If the child ran for < 3 seconds, your program should print:
Blast that grotesque ganglion! You let them get away!
If the child ran for >= 3 seconds, your program should print:
Sayonara you shell-backed simpletons. I'll get you next time!
If the child was terminated because it ran >= 5 seconds:
Tonight I dine on turtle soup! Muhaha!
Below, is some sample runs of the program to compare against.
#> ./shredder
Tonight I dine on turtle soup! Muhaha!
#> ./shredder ls
Makefile shredder shredder.c
Blast that grotesque ganglion! You let them get away!
#> ./shredder sleep 2
1: tick-tock
2: tick-tock
Blast that grotesque ganglion! You let them get away!
#> ./shredder sleep 4
1: tick-tock
2: tick-tock
3: tick-tock
4: tick-tock
Sayonara you shell-backed simpletons. I'll get you next time!
#> ./shredder sleep 5
1: tick-tock
2: tick-tock
3: tick-tock
4: tick-tock
5: tick-tock
Tonight I dine on turtle soup! Muhaha!
#> ./shredder cat
1: tick-tock
2: tick-tock
3: tick-tock
4: tick-tock
5: tick-tock
Tonight I dine on turtle soup! Muhaha!
#> ./shredder BAD_FILE
execvp: No such file or directory
Blast that grotesque ganglion! You let them get away!
3 PART 2: More Sons: Hanlding SIGCHLD
Whenever a child proces changes state, either because it terminated
or was stopped or was continued, a signal is sent to the
parent. That signal is SIGCHLD
and it can be handled in the same
way as other signals. What makes handling SIGCHLD
different,
though, is that you can take actions based on child state.
In this part of the lab, we will return to the foursons
program
but this time the child process are up to even more antics. You are,
again, required to print information about the state change of the
children, and to do so, you will use sigaction()
and the
siginfo_t
structure. Refer to the man page for more information.
3.1 Task 2 moresons
For this task, change into the sigaction
directory in the lab
directory. In there, you will find the source file moresons.c
,
which you will complete. Your program must meet the following
specification:
- It must use
sigaction()
with the appropriatesa_action
handler and flags to act uponSIGCHLD
signals. - In the handler, if a child stopped, it must be continued with
SIGCONT
. - When a child changes state, an appropriate message must be printed depending on if the child was stopped, continued, exited, or was terminated by a signal.
- All messages and logic for child handling must occur in the signal handler.
Here are sample executions of the program to compare against:
#> ./moresons
Child 0: 14357: Sending myself SIGSTOP
Child 1: 14358: I'm going to dereference a NULL pointer eventually
Child 2: 14359: Scheduling an alarm for 1 second
Parent: Child 0: 14357 stopped, continuing ...
Child 3: 14360: Ummm .... exit 0?
Parent: Child 1: 14358 stopped, continuing ...
Parent: Child 1: 14358 just continued
Parent: Child 3: 14360 terminated and exited with status 0
Parent: Child 1: 14358 terminated and exited due to signal no. 11
Parent: Child 2: 14359 terminated and exited due to signal no. 14
#> ./moresons
Child 0: 14363: Sending myself SIGSTOP
Child 1: 14364: I'm going to dereference a NULL pointer eventually
Child 2: 14365: Scheduling an alarm for 1 second
Child 3: 14366: Ummm .... exit 0?
Parent: Child 1: 14364 stopped, continuing ...
Parent: Child 0: 14363 stopped, continuing ...
Parent: Child 0: 14363 just continued
Parent: Child 3: 14366 terminated and exited with status 0
Parent: Child 1: 14364 terminated and exited due to signal no. 11
Parent: Child 2: 14365 terminated and exited due to signal no. 14
Finally, note that the child's number and the child's pid are not the
same. Based on the pid in the siginfo_t
structure you will need to
look up the child's number in the c_pid
array – the index in the
array is the child's number and the value is the pid.