Computer Communications Fall 1998
The last assignment introduced the setitimer and getitimer system calls that can be used to obtain various forms of system time. But a more frequent use of setitimer is to allow programs to time-out, or be notified of an excessive waiting time, in certain situations. Alternatively, the alarm call can be used instead of setitimer (you can use man alarm to read about the alarm system call).
Suppose you have a program sets an alarm, using the setitimer, to trigger in ten seconds. Then ten seconds after your program sets the alarm, the system will send your program a signal as notification. There are many kinds of signals that the system can send your program (the alarm signal, which is called SIGALRM, is only one of them). You can see an overview of various system calls dealing with signals using the command man signal.
What happens after the system sends your program a signal? If your program is prepared to receive the signal, then a special subroutine in your program will be called by the system; if no such special subroutine exists, your program will be terminated by the system. Before your program can correctly process a signal, it must tell the system about what kinds of signals it is able to process -- and there are system calls for this purpose.
Timeouts are necessary in many network applications, and these require using alarms or setitimer calls. To learn how timeouts and signals work, copy the sigtime.c program to your directory and compile it (with the command cc -o sigtime sigtime.c or if that fails, try gcc -o sigtime sigtime.c). When you run sigtime, you can either wait for thirty seconds and the program will quit, or give it some keyboard input. Each time you give the program input, the timeout timer is reset.
After you have experimented with the program, use man signal, man alarm, and man sigaction to learn about Unix signals. Then edit the program and comment out the doSigSet() call in the main program, recompile and test it -- this shows what happens when an alarm signal occurs but a program has not prepared for such a signal.
The sigtime.c program uses the getchar() system call to read characters from the standard input. What happens if the system sends sigtime an alarm signal during execution of the getchar() call? After all, most of the time sigtime is waiting for input from the keyboard, which is hidden inside the getchar() call. Somehow, the getchar() function hides the alarm signal -- allowing the program to be notified, but not changing the fact that it is waiting for input. But what if we wanted the getchar() function to stop executing when the system sends an alarm signal? Unfortunately, it is not possible to do this -- getchar() appears to tolerate any interruptions and continue to wait. However most other system functions work differently.
If you look carefully at the output from man 2 read you will see that the read() system function does not hide signals. If your program receives a signal while executing a read() function, then that read() function will fail -- and your program may need to retry the read() again. But can't read() fail for many reasons, such as I/O errors? Yes -- so there has to be some way for your program to distinguish between real errors and signals. There is a standard way to test for this in programs, which you will see often in network programs.
To illustrate how programs deal with signals during execution of system calls, we have a simple example. Copy the sighandle.c program to your directory and compile it (with the command cc -o sighandle sighandle.c or if that fails, try gcc -o sighandle sighandle.c). When you run sighandle, it waits for data from the keyboard. Try various forms input to the program while it is running (use control-c or some equivalent way to kill it if you want to stop it from running).
The Homework Questions
178 homework 2, student 6789If you do not have such a subject line, I will bounce your letter back to you and ask for a resubmission of the homework.