Upload
lucinda-short
View
216
Download
2
Embed Size (px)
Citation preview
4061 Session 15 (3/6)
Today
• More about signals
• A (relevant) aside
• Quiz review
Today’s Objectives• Give an example of how signals might be
used in a real-world application
• Identify reentrant and non-reentrant code
• Give examples of functions that are safe and not safe to use in a signal handler
• State what happens when system calls are interrupted by signals
Admin
• Homework 2
• Homework 3
• Quiz 3
Signals Case Study: Apache
• Apache httpd is web server software
• It is designed to maximize such things as uptime and efficiency
• It has a parent thread which coordinates activity, and several (or many) children which handle web requests
Signals Case Study: Apache
• Httpd comes with a shell script that makes it easy to start, stop, and restart the server
• Uses signals to deliver messages to the parent– TERM: stop now– USR1: graceful restart– HUP: restart
• What happens with kill -9 <httpdpid>?• http://httpd.apache.org/docs/2.0/stopping.html
Another Signals Use Case
• Implement a “quality feedback agent” for a piece of software
• After the software crashes, or is forced shut, the next time it’s run, it asks to send an email to its developers
Interrupted Operations
• What happens when a signal interrupts a system call?– It depends!– “Fast” system calls are not– “Slow” system calls are interrupted, and so
are I/O ops (read/write)
Slow Calls
• Slow system calls can block for a long time, or forever. These include:– Reads and writes that can block indefinitely
(e.g. pipe)– Opens that can block indefinitely (e.g. fifo)– pause() and wait()
Interrupted Slow Calls
• Operations that can be interrupted include EINTR among their error returns.– For most I/O operations, only "slow" devices will ever
be interrupted.
• If an operation returns , it is guaranteed not to be partially completed.
• On Linux, but not on Solaris, the default behavior is to automatically retry interrupted operations.– If you use sigaction(), you can set the SA_RESTART
flag to enforce this behavior.
Revisiting Read/Write
• Recall: these functions are not guaranteed to read or write the amount specified
• One reason (among several) is that they may be preempted by a system call
• If these functions return -1, you should check errno for EINTR– This indicates a signal interrupted the call
before it read or wrote any data
Revisiting Read/Write
• Some systems automatically restart system calls (BSD >=4.2, linux, mac os)
• Some do not (solaris)
• What’s the difference?
• Can be overridden (either way) using a flag in sigaction
Reentrant Codeint g_var = 1;
int f() {
g_var = g_var + 2;
return g_var;
}
int g() {
return f() + 2;
}
int f(int i) {
int priv = i;
priv = priv + 2;
return priv;
}
int g(int i) {
int priv = i;
return f(priv) + 2;
}
Example from: http://en.wikipedia.org/wiki/Reentrant
Make me reentrant1. Why is this code non-reentrant?2. Make me reentrant.
char *strToUpper(char *str) { static char buffer[STRING_SIZE_LIMIT]; int index;
for (index = 0; str[index]; index++) buffer[index] = toupper(str[index]); buffer[index] = '\0'; return buffer;}
Signal Handler Safety
• What can you "safely" do inside a signal handler?– Remember that any function you use in a
signal handler could also be in use in your program when the signal arrives
Malloc and free
• Malloc and free are non-reentrant• Why?
– As part of allocating and freeing memory, the process must track the parts of its address space that are free and occupied
– One common way to do so is to use a linked list to track allocated regions of the heap
• Doom:– We’re in the middle of a malloc– We’re interrupted by a signal– The signal handler calls malloc
Safe Calls in Signal Handlers
• Reentrant functions and “atomic” signal handlers• The UNIX spec lists 118 functions that are
reentrant, and thus safe to use in signal handers– read/write– stat– open– wait– ...