Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > SIGALRM in a class member?

Reply
Thread Tools

SIGALRM in a class member?

 
 
Ron Eggler
Guest
Posts: n/a
 
      08-12-2008
Hi there,

I need to provide a heartbeat to a device cyclic after a specified time (~
1second range).
I do have a communication class and will need to use such in order to send
the heartbeat string to the client device.
Now I would have liked to use following functions:
signal( SIGALRM, sendHeartbeat );
alarm(atoi(INITSource::XMLread(inBufstr,"Cyclic"). c_str()));
but the problem is signal wouldn't allow me to have a function pointer to a
member method like INITSource::sendHeartbeat. If I need to do it this way I
would end up in crazy static declarations and linker conflicts - I have
gone there already and apparently didn't solve it... So I went back and
came to ask here - any suggestions?

Thanks,
Ron
--
weeks of software enineering safe hours of planing
 
Reply With Quote
 
 
 
 
Ron Eggler
Guest
Posts: n/a
 
      08-12-2008
Ron Eggler wrote:

> Hi there,
>
> I need to provide a heartbeat to a device cyclic after a specified time (~
> 1second range).
> I do have a communication class and will need to use such in order to send
> the heartbeat string to the client device.
> Now I would have liked to use following functions:
> signal( SIGALRM, sendHeartbeat );
> alarm(atoi(INITSource::XMLread(inBufstr,"Cyclic"). c_str()));
> but the problem is signal wouldn't allow me to have a function pointer to
> a member method like INITSource::sendHeartbeat. If I need to do it this
> way I would end up in crazy static declarations and linker conflicts - I
> have gone there already and apparently didn't solve it... So I went back
> and came to ask here - any suggestions?
>
> Thanks,
> Ron


Actually I figured out a way to do it. I don't know if it's a detour tho.
I just declared a C style pointer to my class and copy the pointer after
instancing the class into this pointer so I now have a C-style function
that gets called by SIGALRM and from there I call the method of my class
kinda like this:
signalhandler (int signal)
{
CopyOfInstance->ExecuteHeartbeat(signal);
}
Does this make sense? Is this a good solution or no?
Thanks for hints and tips!

Ron
--
weeks of software engineering safe hours of planing
 
Reply With Quote
 
 
 
 
Ron Eggler
Guest
Posts: n/a
 
      08-13-2008
R Samuel Klatchko wrote:

> Ron Eggler wrote:
>> signal( SIGALRM, sendHeartbeat );
>> alarm(atoi(INITSource::XMLread(inBufstr,"Cyclic"). c_str()));
>> but the problem is signal wouldn't allow me to have a function pointer to
>> a member method like INITSource::sendHeartbeat. If I need to do it this
>> way I would end up in crazy static declarations and linker conflicts - I
>> have gone there already and apparently didn't solve it...

>
> You can do this with a forwarding function that is a static member (you
> can also do it with a non-member function). Because signal does not
> give you a way to attach some caller defined data, you will also need a
> static member variable to hold a pointer to the instance of the class
> you want to use:
>
> foo.h:
> class foo
> {
> public:
> foo()
> {
> signal(SIGALRM, sighandler_trampoline);
> singleton = this;
> }
>
> private:
> static void sighandler_trampoline(int sig)
> {
> singleton->sighandler(sig);
> }
>
> void sighandler(int sig)
> {
> // add your logic here
> }
>
> static foo *singleton;
> };
>
> foo.cpp:
> foo *foo::singleton = 0;
>
> samuel

Hey Samuel,

This is kinda what I do -see my other posting except that I copy my instance
like this:
gps = new INITSource(source, 51001, log, gpsDataObj, false);
Glob_INIT_i = dynamic_cast<INITSource*>(gps);

I have to cast it again because gps is from a different type (mother class
of INITSource)

--
weeks of software enineering safe hours of planing
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      08-13-2008
On Aug 13, 1:57 am, R Samuel Klatchko <(E-Mail Removed)> wrote:
> Ron Eggler wrote:
> > signal( SIGALRM, sendHeartbeat );
> > alarm(atoi(INITSource::XMLread(inBufstr,"Cyclic"). c_str()));
> > but the problem is signal wouldn't allow me to have a function pointer to a
> > member method like INITSource::sendHeartbeat. If I need to do it this way I
> > would end up in crazy static declarations and linker conflicts - I have
> > gone there already and apparently didn't solve it...


> You can do this with a forwarding function that is a static
> member (you can also do it with a non-member function).


Not according to the standard. "All signal handlers shall have C
linkage" (§18.7/5). And "A C language linkage is ignored for the
names of class members and the member function type of class
member functions" (§7.5/4). A compiler is required to diagnose
this error (and some do).

> Because signal does not give you a way to attach some caller
> defined data, you will also need a static member variable to
> hold a pointer to the instance of the class you want to use:


Note, however, that it is implementation defined whether you can
access said variable. Typically, if it is a pointer, you can,
but calling a member function on it, etc., is less sure.

Since you can only deal with one instance this way (and since at
least under Unix, SIGALRM only manages a single timer), the best
solution is to declare a sig_atomic_t with static lifetime, and
test it. (Except that most systems, or at least Unix and
Windows, offer even better facilities for managing time.)

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      08-13-2008
On Aug 13, 5:32 am, Jack Klein <(E-Mail Removed)> wrote:
> On Tue, 12 Aug 2008 23:58:11 GMT, Ron Eggler <(E-Mail Removed)>
> 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
> indeterminate."


> 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. 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().

> 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.


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.)

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
Ron Eggler
Guest
Posts: n/a
 
      08-13-2008
James Kanze wrote:

> On Aug 13, 5:32 am, Jack Klein <(E-Mail Removed)> wrote:
>> On Tue, 12 Aug 2008 23:58:11 GMT, Ron Eggler <(E-Mail Removed)>
>> 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
>> indeterminate."

>
>> 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.

> 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
ulibC.
Why would having an independent thread make more sense than just raising a
timer signal SIGALRM? I don't quite see the problem...

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).

Ron

--
weeks of software enineering safe hours of planing
 
Reply With Quote
 
Ron Eggler
Guest
Posts: n/a
 
      08-13-2008
I also replaced my atoi(string from XML parser) to this:

istringstream buffer(INITSource::XMLread(inBufstr,"Cyclic"));
buffer >> HeartBeatTime;
HeartBeatTime=float(float(HeartBeatTime)/100*90);
alarm(HeartBeatTime);

What do you think to this, is this better? This should work properly as well
and is C++ conform, any other suggestions or hints regarding this
conversion?

Thanks,
Ron
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      08-14-2008
On Aug 14, 12:26 am, Ron Eggler <(E-Mail Removed)> wrote:
> James Kanze wrote:
> > On Aug 13, 5:32 am, Jack Klein <(E-Mail Removed)> wrote:
> >> On Tue, 12 Aug 2008 23:58:11 GMT, Ron Eggler <(E-Mail Removed)>
> >> 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
> >> indeterminate."


> >> 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?


That the behavior is undefined. Anything the implementation
does is correct. The implementation can refuse to compile it,
cause a core dump or reformat your hard disk when it is
executes, or ... define it to do something specific.

Posix does define some additional things with regards to
signals, including asynchronous signals. Presumable, so does
any non-Posix system which defined SIGALRM; it wouldn't make
much sense otherwise.

> 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.


The fact that you have undefined behavior doesn't mean that it
won't work. In this case, there are two aspects to consider:

-- Posix does define asynchronous signals, and SIGALRM. If
you're on a Posix conformant system (or one that is at least
conformant in this regard: any of the *nix, and I think even
Windows), catching the signal in your handler is defined,
and you have a few more defined options than just writing to
a sig_atomic_t (but not really very many). So it's likely
that that part of your code is defined on your system.

-- Undefined behavior doesn't mean that the code is guaranteed
to fail. According to Posix, for example, it is undefined
behavior to call any of the FILE* functions in a signal
handler. In practice, it's likely to work most of the time;
it all depends on exactly when the signal arrives (with
respect to what other things you're doing).

What you can and cannot do here depends on your system, not on C
or C++. So you really have to take it up in detail in a system
specific newsgroup. Before doing that, however, I would suggest
that you read up on signal handling under Unix. The use of
signal() is NOT recommended; you should be using sigaction()
instead. (And it sounds to me like you actually need threads,
and a dedicated thread to handle the signals. This is the most
common solution under Unix, since it means that you actually
handle the signal in a thread, and not in a signal handler, and
thus have access to literally everything the system offers.)

> > 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.


Just setting sig_atomic_t? That won't get you very far.

> >> 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?


No. The fact that you're not allowed to call most functions
from a signal handler. See the Signal Concepts section in the
Posix standard
(http://www.opengroup.org/onlinepubs/...399/functions/
xsh_chap02_04.html).
Or better yet, get a good, up to date book about Unix
programming (e.g. "Advanced Programming in the UNIX
Environment", by W. Richard Stevens, ISBN 0-201-56317-7).
Handling signals and other asynchronous events is not trivial,
and requires some understanding.

> > 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.


Close enough in this regard. I'm pretty sure that Linux gives
all of the Posix guarantees with regards to signals. It may
give some more, but I'm not aware of it.

> It's just a customized distribution built on ulibC. Why would
> having an independent thread make more sense than just raising
> a timer signal SIGALRM? I don't quite see the problem...


The problem is that you're trying to respond asynchronously.
Which means that you're interrupting one activity to do
something else, and that you have to be careful using common
state. Except that in many case, you don't see the common
state; it's hidden somewhere in the system routines. (Malloc is
an obvious example; in order to work, malloc needs to maintain
global state concerning what is and is not being used. And
during a call to malloc, there will be moments when that global
state is inconsistent. If your signal handler is called at one
of those times, and calls malloc, the malloc called from the
signal handler will see an inconsistent state, and likely crash,
or do something else disagreeable.)

> 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).


Well, I've not really understood what you're trying to do. Most
of the time, when I need a keep alive, I'll be waiting on a
socket or a condition. In such cases, I'll just add a timeout
to the wait, and send the keep alive if I return because of the
timeout.

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      08-14-2008
On Aug 14, 12:38 am, Ron Eggler <(E-Mail Removed)> wrote:
> I also replaced my atoi(string from XML parser) to this:


> istringstream buffer(INITSource::XMLread(inBufstr,"Cyclic"));
> buffer >> HeartBeatTime;
> HeartBeatTime=float(float(HeartBeatTime)/100*90);
> alarm(HeartBeatTime);


> What do you think to this, is this better?


If it is in a signal handler, it's undefined behavior.

> This should work properly as well and is C++ conform, any
> other suggestions or hints regarding this conversion?


You can't do anything this complicated in a signal handler
without incurring undefined behavior.

Note that C++ is even trickier with regards to signal handlers,
since Posix makes no guarantees concerning C++. In general, you
can count on being able to do anything you could do from a
signal handler in C, but nothing more. You cannot do *anything*
which uses any of the iostream stuff, or FILE*. You cannot call
any of the functions defined in the C++ standard. Of the
functions defined in the C standard, I think time(), rename(),
signal() and abort() are the only ones allowed (unless I've
missed one).

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
SIGALRM problem Paul Rubin Python 2 10-13-2008 06:39 PM
Is SIGALRM getting masked ??? apoorva.groups@gmail.com C Programming 1 12-30-2007 10:08 PM
Catching SIGALRM in a thread Samuel Perl Misc 7 05-23-2007 09:55 PM
SIGALRM available? Guillaume Marcais Ruby 2 02-15-2005 02:43 PM
timeouts with threads and SIGALRM Eric Schwartz Ruby 11 08-19-2004 11:57 PM



Advertisments