Lab 4: Pipes and Signal Handling
These questions were written by Jerry Cain and Ryan Eberhardt.
Before the end of lab, be sure to fill out the lab checkoff sheet here!
Problem 1: Incorrect Output File Redirection
The publish
user program takes an arbitrary number of filenames as arguments
and attempts to publish the date and time (via the date
executable that ships
with all versions of Unix and Linux). publish
is built from the following
source:
static void publish(const char *name) {
printf("Publishing date and time to file named \"%s\".\n", name);
int outfile = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0644);
dup2(outfile, STDOUT_FILENO);
close(outfile);
if (fork() > 0) return;
char *argv[] = { "date", NULL };
execvp(argv[0], argv);
}
int main(int argc, char *argv[]) {
for (size_t i = 1; i < argc; i++) publish(argv[i]);
return 0;
}
Someone with a fractured understanding of processes, descriptors, and file redirection might expect the program to have printed something like this:
$ ./publish a.txt b.txt c.txt d.txt
Publishing date and time to file named "a.txt".
Publishing date and time to file named "b.txt".
Publishing date and time to file named "c.txt".
Publishing date and time to file named "d.txt".
However, that’s not what happens. You should step through this cplayground to visualize what is happening.
Questions:
- What text is actually printed to standard output?
- What do each of the four files contain?
- How should the program be rewritten so that it works as intended?
Problem 2: Implementing timeout
timeout
is a helpful program that will run a command, killing it with
SIGKILL
if it exceeds a specified duration. The timeout
program exits with
the same return code as the child, or 128 + terminatingSignalNum
if the child
was killed by a signal:
🍉 ./timeout 2 sleep 1
🍉 echo $?
0
🍉 ./timeout 2 sleep 3
👾 echo $?
137
# ^ 128 + 9 (SIGKILL)
Note: the real timeout
that ships with Linux sends SIGTERM
by default and
exits with status 124
if the child timed out, but for simplicity, we’ll use
the specification above.
In this problem, you’ll implement your own version of timeout
. Take a look at
the starter code in this
cplayground. The starter code
parses a duration
and NULL
-terminated childArgv
from the command line
arguments. Note that command line arguments are set in the settings sidebar
(click the gear icon in the top left).
Your job is to:
- Start a child process running
childArgv
- Right after spawning the child, use the
alarm
syscall to tell the OS to send youSIGALRM
at a timeduration
seconds in the future - If
SIGALRM
comes in before the child process exits, terminate it withSIGKILL
- Wait for the child to exit, and make sure the parent exits with the same
status as the child (or
128 + signalNum
if the child was killed by a signal – useWIFSIGNALED
andWTERMSIG
)
You can assume the child won’t stop/continue, so you don’t need to think about
WUNTRACED
or WCONTINUED
, and you don’t need to worry about handling
multiple SIGCHLD
signals.