CSE 522S: Studio 12

Linux Signal Handling

Signals are a simple yet powerful way for Linux processes to communicate in pre-defined ways. They are ideally suited for inter-process event handling during system operation. Signals can be sent to any process in the system, and can be recieved by defining special functions called signal handlers, which are executed upon receipt of the signal.

In this studio, you will:

  1. Generate and recieve program signals
  2. Create custom signal handlers

Please complete the required exercises below, as well as any optional enrichment exercises that you wish to complete.

As you work through these exercises, please record your answers, and when finished email your results to dferry@email.wustl.edu with the phrase Linux Signals in the subject line.

Make sure that the name of each person who worked on these exercises is listed in the first answer, and make sure you number each of your responses so it is easy to match your responses with each exercise.

Required Exercises

  1. As the answer to the first exercise, list the names of the people who worked together on this studio.

  2. For the first exercise we will find an existing program to handle signals with a custom signal handler. Find a clean copy of the dense_mm program that we used earlier. Build this program and run it. While this program is executing, send it the keyboard interrupt signal (SIGINT) by highlighting its terminal and pressing CTRL+C (hold down the CTRL button and press C). As the answer to this exercise, copy and paste the result from successfully interrupting your program.

  3. There are many signals that can be sent or recieved in Linux. An overview of the signalling mechanism can be found at the manual page man 7 signal. Some commonly used signals are SIGINT (keyboard interrupt), SIGQUIT (quit from keyboard), and SIGTERM (terminate process). Every signal in the system is associated with a default action (which typically terminates the recieving process), but this can be overridden simply by defining your own signal handling function, which is what we will now do.

    The modern, portable way to define a signal handler is to use the function sigaction() which is documented at man sigaction. Use this function to define a new handler for SIGINT. You will need to:

    Declare a global counter and increment it when the handler function is called. At the end of your main() function print the value of this counter. Copy and paste a sample program output as the answer to this exercise.

    NOTE: Overriding the SIGINT handler may make it difficult to terminate your program. You can alternately use CTRL+\ to send the SIGQUIT signal or the kill program to terminate your processes.

  4. One way that signal handlers are special functions is that they execute asynchronously with respect to the rest of a program. When called, they may interrupt the normal execution of the program at virtually any point. Consider what might happen, for example, if the same function is called from both the regular program flow as well as a signal handler. This could result in the function being called concurrently from two different contexts, even within a single-threaded program! This could cause data corruption or even deadlock if not handled appropriately.

    Even library functions are not immune to problems with asynchronicity. Download the program print5000.c, build and run it. This is a very simple program that defines a signal handler for SIGINT, and then prints the numbers from 1 to 5000 in order. Try running this program and interrupting it with SIGINT. Inspect the program output where it was possibly interrupted by a signal handler.

    What happens? Copy and paste evidence.

  5. For the reasons outlined above, it is not safe to make many common system calls or library function calls from within a signal handler. Many such functions, such as printf() are not guaranteed to execute correctly when called from within a handler, since they may be called concurrently from different contexts. Fortunately, there is a list of functions that is guaranteed to be safe when called from a handler. These functions are given in the signal documentation at man 7 signal under "Async-signal-safe functions".

    Going back to your original program, use the write() function documented at man 2 write to produce output from within a signal handler. In particular, you must:

Things to turn in: