Re: SIGALRM in a class member?
On Wed, 13 Aug 2008 22:26:29 GMT, Ron Eggler <firstname.lastname@example.org>
wrote in comp.lang.c++:
James Kanze wrote:
On Aug 13, 5:32 am, Jack Klein <jackkl...@spamcop.net> wrote:
On Tue, 12 Aug 2008 23:58:11 GMT, Ron Eggler <unkn...@example.com>
wrote in comp.lang.c++:
While you've made a number of important points:
Note the reference to the C signal handler definition, which states:
"If the signal occurs other than as the result of calling the
abort or raise function, the behavior is undefined if the
signal handler calls any function in the standard library
other than the signal function itself (with a first argument
of the signal number corresponding to the signal that caused
the invocation of the handler) or refers to any object with
static storage duration other than by assigning a value to a
static storage duration variable of type volatile
sig_atomic_t. Furthermore, if such a call to the signal
function results in a SIG-ERR return, the value of errno is
Then, in a footnote, the C standard adds:
"If any signal is generated by an asynchronous signal handier,
the behavior is undefined."
In other words, according to the C standard, any signal
generated by SIGALRM is undefined behavior.
What does undefined behaviour in this matter mean exactly? It's been raised
properly for me. I don't see the problem as long as I check in the actual
timer function what kind of signal i got it seems to work nicely.
Neither C nor C++ guarantees nor defines reentrancy, although C++ is
moving in that direction for the future. But even then, these
features are generally defined for threading, and have certain
Depending on your platform and quite a few other things, signals might
actually be generated by hardware interrupts at times that are
completely unpredictable to not only your program, but the C++ and C
libraries underneath them.
Suppose, just for example, that your code is in the middle of another
operation on the same object of the INITSource class. It might be in
a state where a new call in the middle of the old one causes
overwriting of some state operation. A function that reads data from
a buffer, whether it is a buffer from a file or not, might have read
some data but not yet stored the updated pointer or index into the
For example, the FILE structure controlling a C stream generally
maintains a pointer or index into the buffer. A C++ stream
implementation might or might not be built on top of the C FILE
Typically, there is something like this pseudo code in a read call,
if (struct.index < BUFF_SIZE)
ch = struct.buffer[struct.index++];
/* call OS read function to fill the buffer again */
ch = struct.buffer;
struct.index = 1;
So what happens if the call has just executed the if statement, then
it is preempted by a signal. A function invoked by a signal than
calls the read function on the same object with the same underlying
stream, which reads some bytes. When the signal function ends and the
interrupted code is resumed, it now starts reading where the signal
handler stopped reading.
Even worse is if the function called during signal handling happened
to read all the remaining bytes in the buffer, leaving the index
member exactly equal to BUFF_SIZE. The resumed code, having already
checked that index was less than BUFF_SIZE, cheerfully tries to read
the byte as one past the end of the array. This may or may not cause
a memory fault of some kind, but certainly returns incorrect data.
The point is that operating systems, which are not defined or
controller by the C or C++ standards, vary greatly and have evolved
over time. On some early platforms, a hardware interrupt could be
dispatched to a signal handler even if the OS kernel itself was in
some sort of non-reentrant critical section. So any OS call at all
from a signal handling function could crash the whole system if the
timing was just right, or should I say wrong. Most modern operating
systems are smarter than that, for sure.
That's true, but if
he's requesting a SIGALRM, he's working under an OS and with a
compiler which supports it, and defines some of the behavior the
C and C++ standards leave undefined. If he's on a Posix
system, what he can and cannot do is defined by the Posix
standard. And while it's still very limited, it is a little bit
more than just setting a sig_atomic_t and calling signal().
I don't need more than what this is offering me.
Be very, very careful trying to use library functions, file
i/o, memory allocation, or just about anything else inside a
signal handler invoked asynchronously (other than by a call to
raise()). The C++ library, the underlying C library, and
maybe even the operating system can be in a state where there
are severe limits on what they can do.
What do you mean by "be careful"? I believe it could end up in a stack
overflow if the actual timer function takes too much time. Is this what you
are referring to?
Yes. He really has to ask in a group specialized for his OS to
find out exactly what he can do. (The usual solution under Unix
is to run a special timer thread, and handle the signal
there---Posix allows a signal to unblock a normal thread, rather
than just invoke a signal handler, and you can then do just
about anything you could normally do in a thread.)
Alright the software I'm writing here is working on an embedded Linux
platform - not POSIX tho. It's just a customized distribution built on
Why would having an independent thread make more sense than just raising a
timer signal SIGALRM? I don't quite see the problem...
Because the POSIX standard requires a conforming OS to make sure it is
in a state where it can accept certain system calls, such as the call
to unblock another thread, as Keith mentioned. So when the unblocked
thread is actually run, the entire system is back in the normal
foreground context, not in the asynchronous interrupted status.
For my application it makes sense just doing it this way I believe -> Trying
to keep memory usage minimal as well as not wasting any CPU ressources
(thread running in idle).
My understanding of multi-tasking operating systems in general is that
a thread idling wastes uses exactly zero CPU resources, but I can't
guarantee that this applies to any, let alone all, Linux kernels.
What I was trying to say, and Keith said perhaps more succinctly, is
that you really need a platform specific group. Now that you've
mentioned your platform, I'd suggest something in the comp.os.linux.*
family, and/or comp.arch.embedded.
You will probably need to provide more information. Features and
limitations of Linux depend very heavily on the exact kernel version,
for example, and other limitations might be affected by the specific
library you are using, as opposed to the standard one.
You just need to realize that true asynchronous multi-tasking is a
complex thing, and need to be approached with some understanding of
its limitations. My original answer was absolutely correct as to what
the C and C++ language standards actually guarantee. What you want to
do is specifically the sort of thing that the C++ standard calls
"implementation-defined", so you need to check with the experts for