Re: SIGALRM in a class member?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • James Kanze

    Re: SIGALRM in a class member?

    On Aug 13, 5:32 am, Jack Klein <jackkl...@spam cop.netwrote:
    On Tue, 12 Aug 2008 23:58:11 GMT, Ron Eggler <unkn...@exampl e.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
    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:james.kan ze@gmail.com
    Conseils en informatique orientée objet/
    Beratung in objektorientier ter Datenverarbeitu ng
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
  • Ron Eggler

    #2
    Re: SIGALRM in a class member?

    James Kanze wrote:
    On Aug 13, 5:32 am, Jack Klein <jackkl...@spam cop.netwrote:
    >On Tue, 12 Aug 2008 23:58:11 GMT, Ron Eggler <unkn...@exampl e.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
    >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 ;)

    Comment

    • Ron Eggler

      #3
      Re: SIGALRM in a class member?

      I also replaced my atoi(string from XML parser) to this:

      istringstream buffer(INITSour ce::XMLread(inB ufstr,"Cyclic") );
      buffer >HeartBeatTim e;
      HeartBeatTime=f loat(float(Hear tBeatTime)/100*90);
      alarm(HeartBeat Time);

      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

      Comment

      • Jack Klein

        #4
        Re: SIGALRM in a class member?

        On Wed, 13 Aug 2008 22:26:29 GMT, Ron Eggler <unknown@exampl e.com>
        wrote in comp.lang.c++:
        James Kanze wrote:
        >
        On Aug 13, 5:32 am, Jack Klein <jackkl...@spam cop.netwrote:
        On Tue, 12 Aug 2008 23:58:11 GMT, Ron Eggler <unkn...@exampl e.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
        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.
        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
        limitations.

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

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

        Typically, there is something like this pseudo code in a read call,
        for example:

        if (struct.index < BUFF_SIZE)
        {
        ch = struct.buffer[struct.index++];
        }
        else
        {
        /* call OS read function to fill the buffer again */
        ch = struct.buffer[0];
        struct.index = 1;
        }
        return ch;

        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
        ulibC.
        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.embed ded.

        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
        "implementa tion-defined", so you need to check with the experts for
        your implementation.

        --
        Jack Klein
        Home: http://JK-Technology.Com
        FAQs for
        comp.lang.c http://c-faq.com/
        comp.lang.c++ http://www.parashift.com/c++-faq-lite/
        alt.comp.lang.l earn.c-c++

        Comment

        • James Kanze

          #5
          Re: SIGALRM in a class member?

          On Aug 14, 12:38 am, Ron Eggler <unkn...@exampl e.comwrote:
          I also replaced my atoi(string from XML parser) to this:
          istringstream buffer(INITSour ce::XMLread(inB ufstr,"Cyclic") );
          buffer >HeartBeatTim e;
          HeartBeatTime=f loat(float(Hear tBeatTime)/100*90);
          alarm(HeartBeat Time);
          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:james.kan ze@gmail.com
          Conseils en informatique orientée objet/
          Beratung in objektorientier ter Datenverarbeitu ng
          9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

          Comment

          Working...