IC221: Systems Programming (SP14)


Home Policy Calendar Syllabus Resources Piazza

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.

  1. Using signal handlers, signal() and sigaction()
  2. Scheduling alarm signals with alarm()
  3. Using siginfo_t when handling SIGCHLD

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:

  1. It must use alarm() and SIGALARM signal handling to count the number of seconds the child process runs.
  2. If the child runs for more than 5 seconds, it must terminate it with a SIGKILL signal.
  3. It must print out different information about the termination state of the child dependent on how long the child ran for.
  4. 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:

  1. It must use sigaction() with the appropriate sa_action handler and flags to act upon SIGCHLD signals.
  2. In the handler, if a child stopped, it must be continued with SIGCONT.
  3. 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.
  4. 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.