SIGALRM in a class member?

Discussion in 'C++' started by Ron Eggler, Aug 13, 2008.

  1. Ron Eggler

    Ron Eggler Guest

    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 ;)
    Ron Eggler, Aug 13, 2008
    #1
    1. Advertising

  2. Ron Eggler

    Ron Eggler Guest

    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 ;)
    Ron Eggler, Aug 13, 2008
    #2
    1. Advertising

  3. Ron Eggler

    Ron Eggler Guest

    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 ;)
    Ron Eggler, Aug 13, 2008
    #3
  4. Ron Eggler

    James Kanze Guest

    On Aug 13, 1:57 am, 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).


    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:
    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
    James Kanze, Aug 13, 2008
    #4
  5. Ron Eggler

    James Kanze Guest

    On Aug 13, 5:32 am, Jack Klein <> wrote:
    > On Tue, 12 Aug 2008 23:58:11 GMT, Ron Eggler <>
    > 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:
    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
    James Kanze, Aug 13, 2008
    #5
  6. Ron Eggler

    Ron Eggler Guest

    James Kanze wrote:

    > On Aug 13, 5:32 am, Jack Klein <> wrote:
    >> On Tue, 12 Aug 2008 23:58:11 GMT, Ron Eggler <>
    >> 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 ;)
    Ron Eggler, Aug 13, 2008
    #6
  7. Ron Eggler

    Ron Eggler Guest

    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
    Ron Eggler, Aug 13, 2008
    #7
  8. Ron Eggler

    James Kanze Guest

    On Aug 14, 12:26 am, Ron Eggler <> wrote:
    > James Kanze wrote:
    > > On Aug 13, 5:32 am, Jack Klein <> wrote:
    > >> On Tue, 12 Aug 2008 23:58:11 GMT, Ron Eggler <>
    > >> 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/009695399/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:
    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
    James Kanze, Aug 14, 2008
    #8
  9. Ron Eggler

    James Kanze Guest

    On Aug 14, 12:38 am, Ron Eggler <> 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:
    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
    James Kanze, Aug 14, 2008
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Is SIGALRM getting masked ???

    , Dec 17, 2007, in forum: C Programming
    Replies:
    1
    Views:
    444
    David Thompson
    Dec 30, 2007
  2. Paul Rubin

    SIGALRM problem

    Paul Rubin, Oct 13, 2008, in forum: Python
    Replies:
    2
    Views:
    439
    Paul Rubin
    Oct 13, 2008
  3. Eric Schwartz

    timeouts with threads and SIGALRM

    Eric Schwartz, Aug 13, 2004, in forum: Ruby
    Replies:
    11
    Views:
    347
    Eric Schwartz
    Aug 20, 2004
  4. Guillaume Marcais

    SIGALRM available?

    Guillaume Marcais, Feb 14, 2005, in forum: Ruby
    Replies:
    2
    Views:
    154
    Guillaume Marcais
    Feb 15, 2005
  5. Samuel

    Catching SIGALRM in a thread

    Samuel, May 20, 2007, in forum: Perl Misc
    Replies:
    7
    Views:
    468
    zentara
    May 23, 2007
Loading...

Share This Page