Tags: 75b52e27, article, comgt, global, gmail, google, itags, linux, lt86732ca3, org, posting, programming, ramesh, sekhar, siddhartha, unix, unix-linux, variables
In article <86732ca3.0410200848.75b52e27.unix-linux.itags.org.posting.google.com>,
ramesh.sekhar.unix-linux.itags.org.gmail.com (siddhartha) wrote:
> Jonathan Adams <jwadams.unix-linux.itags.org.gmail.com> wrote in message > news:<jwadams-15D071.03585920102004.unix-linux.itags.org.news1nwk.sfbay.sun.com>... > Hi Jonathan, > I'm a relative newbie to signals - could you clarify your last > statement with an example?
> Jonathan Adams <jwadams.unix-linux.itags.org.gmail.com> wrote in message
> Hi Jonathan,
> I'm a relative newbie to signals - could you clarify your last
> statement with an example?
(added comp.unix.programmer, and set Followup-To:, since this is all
outside of the C standard, and POSIX has the most to say about it)
The problem with signals is that they interrupt the program at an
uncertain point in the text -- you could be in the middle of (say)
updating the malloc() bookkeeping information. If you are, then
calling any function which can invoke malloc() from the signal handler
would almost certainly hopelessly mess up the malloc() heap, causing
random data corruption.
In a multithreaded process, you're likely to just deadlock, since there
will be a lock protecting the malloc state which you are already holding.
Practically, this severely restricts what you can do in a signal handler.
Without further precautions, you can only safely:
1. assign a value to a (possibly volatile) sig_atomic_t variable.
2. mess with local state on the stack
3. call async-signal-safe functions. These are functions which
are "reentrant" (basically, those which do not manipulate any
kind of global state -- strcmp() and strlen() are good
examples, as are most system calls, since the kernel can
Typical "bad ideas" one sees in signal handlers are:
1. calling printf(), fprintf(), or any other stdio function
which acts on a FILE *, directly or indirectly.
(fputs(), puts(), etc.)
2. calling anything which might call malloc().
(sprintf()/snprintf() are insidious examples, because
many implementation of them can call malloc() unexpectedly.)
You also see people calling fork()+exec() in signal handlers, which is
not *precisely* unsafe, but a bit ill-advised. Many gnome
applications do this, in order to pop up "I got a bad signal, what
should I do?" windows.
The simple fact is that signal handlers are very hard to write correctly
once you get beyond simple cases. (and even simple cases introduce
issues like EINTR and SA_RESTART, which can have program-wide effects)
Throw multi-threaded programming into the mix, and now you have *two*
subtly incompatible asynchronous mechanisms, which is why most robust MT
programs block all asynchronous signals in all threads, and have a
dedicated thread in sigwaitinfo(3thr) or sigtimedwait(3thr) handling all
To get back to your original question, strtok() cannot be made
async-signal-safe because it's interface relies on a piece of global
data. Calling it from a signal handler will smash that data, with no
way to recover the previous state.
fopen() uses malloc(), which is not safe. It also has to maintain the
global list of open files, for fflush(NULL) to find.
 For example, you could block the signal whenever you call into any
code which uses the unsafe functions. This can quickly lead to
out-of-hand code complexity, though.
 The worst case of this I've ever seen was a daemon which tried to
"save" itself from SIGSEGVs by fork()ing and exec()ing a new copy of
itself. Of course, the signal handler was buggy, and could deadlock...
Leave a comment...
- 0 Comments