Error passing function in signal( ... )

Discussion in 'C++' started by Dudebot, Dec 29, 2010.

  1. Dudebot

    Dudebot Guest

    Hi Gurus, I'm porting some C code into a C++ environment. I have
    working signal code in C:

    #includes for signal...

    static void exit_gracefully()
    {
    *control = STOP|TWSIEN; // send stop signal
    exit( 0 );
    }

    int main( int argc, char **argv )
    {
    ....
    signal( SIGTERM, exit_gracefully );

    However, when I try to port it into a class, e.g.

    class ADC {
    public:
    ....
    void sample(); // sample ADC

    private:
    volatile unsigned int *control;
    void exit_gracefully();
    };

    void ADC::exit_gracefully()
    {
    *control = STOP|TWSIEN; // send stop signal
    exit( 0 );
    }

    void ADC::sample()
    {
    ....
    signal( SIGTERM, exit_gracefully );

    I get these compilation errors:

    error: argument of type `void (ADC::)()' does not match `void
    (*)(int)'

    I can't pull exit_gracefully() out of the class, as it needs to access
    the private member control.

    I tried casting the function in the signal call
    signal( SIGTERM, void (*)(int) exit_gracefully );

    But I'm getting
    error: parse error before `)' token

    I tried all sorts of typedef conconctions a la
    http://www.parashift.com/c -faq-lite/pointers-to-members.html#faq-33.5,
    but can't get anything to help.

    Any ideas?

    Many TIA,
    Craig
    Dudebot, Dec 29, 2010
    #1
    1. Advertising

  2. On 2010-12-29, Dudebot <> wrote:
    > Hi Gurus, I'm porting some C code into a C++ environment. I have
    > working signal code in C:
    >
    > #includes for signal...
    >
    > static void exit_gracefully()
    > {
    > *control = STOP|TWSIEN; // send stop signal
    > exit( 0 );
    > }
    >
    > int main( int argc, char **argv )
    > {
    > ...
    > signal( SIGTERM, exit_gracefully );
    >
    > However, when I try to port it into a class, e.g.
    >
    > class ADC {
    > public:
    > ...
    > void sample(); // sample ADC
    >
    > private:
    > volatile unsigned int *control;
    > void exit_gracefully();
    > };
    >
    > void ADC::exit_gracefully()
    > {
    > *control = STOP|TWSIEN; // send stop signal
    > exit( 0 );
    > }
    >
    > void ADC::sample()
    > {
    > ...
    > signal( SIGTERM, exit_gracefully );
    >
    > I get these compilation errors:
    >
    > error: argument of type `void (ADC::)()' does not match `void
    > (*)(int)'
    >


    Yes. They have different types.

    > I can't pull exit_gracefully() out of the class, as it needs to access
    > the private member control.


    You could implement get/set methods for this variable.
    Another way is to declare the exit_gracefully function as static,
    so its type will be "void (*)(int)"

    >
    > I tried casting the function in the signal call
    > signal( SIGTERM, void (*)(int) exit_gracefully );
    >
    > But I'm getting
    > error: parse error before `)' token
    >
    > I tried all sorts of typedef conconctions a la
    > http://www.parashift.com/c -faq-lite/pointers-to-members.html#faq-33.5,
    > but can't get anything to help.


    You used the wrong link. See point 33.2 in the same FAQ.

    >
    > Any ideas?
    >
    > Many TIA,
    > Craig
    Pavel Borzenkov, Dec 29, 2010
    #2
    1. Advertising

  3. Dudebot

    Ian Collins Guest

    On 12/30/10 11:39 AM, Dudebot wrote:
    > Hi Gurus, I'm porting some C code into a C++ environment. I have
    > working signal code in C:


    <snip>


    > I get these compilation errors:
    >
    > error: argument of type `void (ADC::)()' does not match `void
    > (*)(int)'


    That's correct, the function signatures don't match.

    > I can't pull exit_gracefully() out of the class, as it needs to access
    > the private member control.


    Then declare it extern "C" and make it a friend of the class.

    --
    Ian Collins
    Ian Collins, Dec 29, 2010
    #3
  4. Dudebot

    Dudebot Guest

    Whoa. This seems like choosing between two bad design options, almost
    a philosophical question.

    Pavel points me to making a wrapper in
    http://www.parashift.com/c -faq-lite/pointers-to-members.html#faq-33.2,
    where the number of caveats is too numerous to count ;)

    Ian tells me to make it extern... meaning, try to match the objects
    perfectly in the compile, and hope for the best.

    Are these really the only two good ways to proceed?

    (Thanks, Pavel and Ian!)

    Craig
    Dudebot, Dec 29, 2010
    #4
  5. Dudebot

    Ian Collins Guest

    On 12/30/10 12:48 PM, Dudebot wrote:
    > Whoa. This seems like choosing between two bad design options, almost
    > a philosophical question.
    >
    > Pavel points me to making a wrapper in
    > http://www.parashift.com/c -faq-lite/pointers-to-members.html#faq-33.2,
    > where the number of caveats is too numerous to count ;)
    >
    > Ian tells me to make it extern... meaning, try to match the objects
    > perfectly in the compile, and hope for the best.


    Hope for the best?

    > Are these really the only two good ways to proceed?


    Well your options are limited by the C interface you are working with.
    You simply can't pass a C++ member function (the signature is wrong)
    some compilers will let you get away with a static member function , but
    the linkage is still wrong.

    The handler function signature means neither a static member or a friend
    function can be passed a pointer to a class instance. Using the int
    parameter to pass some form of index might be your only option.

    --
    Ian Collins
    Ian Collins, Dec 30, 2010
    #5
  6. Dudebot

    Jorgen Grahn Guest

    On Wed, 2010-12-29, Dudebot wrote:
    > Hi Gurus, I'm porting some C code into a C++ environment. I have
    > working signal code in C:
    >
    > #includes for signal...
    >
    > static void exit_gracefully()
    > {
    > *control = STOP|TWSIEN; // send stop signal
    > exit( 0 );
    > }


    That's not really a "graceful" exit in C++ -- your destructors won't
    run. May or may not matter to your application, of course ...

    The simple workaround is to throw an exception instead and catch it
    in main().

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Oo o. . .
    \X/ snipabacken.se> O o .
    Jorgen Grahn, Dec 30, 2010
    #6
  7. Jorgen Grahn <> writes:
    > Dudebot wrote:


    >> Hi Gurus, I'm porting some C code into a C++ environment. I have
    >> working signal code in C:
    >>
    >> #includes for signal...
    >>
    >> static void exit_gracefully()
    >> {
    >> *control = STOP|TWSIEN; // send stop signal
    >> exit( 0 );
    >> }

    >
    > That's not really a "graceful" exit in C++ -- your destructors won't
    > run. May or may not matter to your application, of course ...


    Destructors of static-duration objects are called by exit(). BUT they
    are almost certainly not safe to run in the context of a signal
    handler (almost nothing is).

    (For that matter C99 doesn't even allow exit() - only _Exit().)

    > The simple workaround is to throw an exception instead and catch it
    > in main().


    Throwing an exception from a signal handler sounds like a very bad plan
    indeed.

    --
    http://www.greenend.org.uk/rjk/
    Richard Kettlewell, Dec 30, 2010
    #7
  8. Dudebot

    James Kanze Guest

    On Dec 30, 2:17 am, Ian Collins <> wrote:
    > On 12/30/10 12:48 PM, Dudebot wrote:


    > > Whoa. This seems like choosing between two bad design options, almost
    > > a philosophical question.


    > > Pavel points me to making a wrapper in
    > >http://www.parashift.com/c -faq-lite/pointers-to-members.html#faq-33.2,
    > > where the number of caveats is too numerous to count ;)


    > > Ian tells me to make it extern... meaning, try to match the objects
    > > perfectly in the compile, and hope for the best.


    > Hope for the best?


    > > Are these really the only two good ways to proceed?


    > Well your options are limited by the C interface you are working with.
    > You simply can't pass a C++ member function (the signature is wrong)
    > some compilers will let you get away with a static member function , but
    > the linkage is still wrong.


    > The handler function signature means neither a static member or a friend
    > function can be passed a pointer to a class instance. Using the int
    > parameter to pass some form of index might be your only option.


    It's not really an option either; you're very, very limited with
    regards to what you can do in a signal handler: you *can't* call
    exit (which he apparently wants to do), you can't even access
    anything C++. According to the C standard, all you can do is
    write (but not read) to a variable with type sig_atomic_t.
    Posix (and presumably Windows) allows a little bit more, but
    nothing which involves C++: you can't do stream IO (FILE* or
    iostream), you can't call a destructor, and you can't throw an
    exception. (You can call _exit or abort, but this won't flush
    any stream buffers.)

    More generally, you probably don't want to, at least if the goal
    is to trigger a clean shutdown. You normally can't start
    a clean shutdown at just anytime, and signals arrive
    asynchronously. The usual solution depends on the application:
    for anything multithreaded under Unix, you can create a special
    signal handler thread; signals will generate an event which
    unblocks the thread, and the thread can start the clean shutdown
    (running as a normal thread, and not as a signal handler). For
    single threaded processes, the usual solution is just to have
    a global sig_atomic_t initialized to zero, set it to one in the
    signal handler, and poll it at appropriate moments.

    --
    James Kanze
    James Kanze, Dec 30, 2010
    #8
  9. Dudebot

    Jorgen Grahn Guest

    On Thu, 2010-12-30, Richard Kettlewell wrote:
    > Jorgen Grahn <> writes:
    >> Dudebot wrote:

    >
    >>> Hi Gurus, I'm porting some C code into a C++ environment. I have
    >>> working signal code in C:
    >>>
    >>> #includes for signal...
    >>>
    >>> static void exit_gracefully()
    >>> {
    >>> *control = STOP|TWSIEN; // send stop signal
    >>> exit( 0 );
    >>> }

    >>
    >> That's not really a "graceful" exit in C++ -- your destructors won't
    >> run. May or may not matter to your application, of course ...

    >
    > Destructors of static-duration objects are called by exit().


    Ok, but the other ones (the vast majority of all objects) are not
    destroyed properly.

    > BUT they
    > are almost certainly not safe to run in the context of a signal
    > handler (almost nothing is).
    >
    > (For that matter C99 doesn't even allow exit() - only _Exit().)
    >
    >> The simple workaround is to throw an exception instead and catch it
    >> in main().


    Sorry, didn't spot that he used actual signals. The comment about
    "send stop signal" in the actual signal handler confused me -- I
    thought he just used the word "signal" for his own purposes.

    > Throwing an exception from a signal handler sounds like a very bad plan
    > indeed.


    Agreed.

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Oo o. . .
    \X/ snipabacken.se> O o .
    Jorgen Grahn, Dec 30, 2010
    #9
  10. Dudebot

    Dudebot Guest

    On Dec 30, 5:33 am, James Kanze <> wrote:

    > More generally, you probably don't want to, at least if the goal
    > is to trigger a clean shutdown.  You normally can't start
    > a clean shutdown at just anytime, and signals arrive
    > asynchronously.  The usual solution depends on the application:
    > for anything multithreaded under Unix, you can create a special
    > signal handler thread; signals will generate an event which
    > unblocks the thread, and the thread can start the clean shutdown
    > (running as a normal thread, and not as a signal handler).  For
    > single threaded processes, the usual solution is just to have
    > a global sig_atomic_t initialized to zero, set it to one in the
    > signal handler, and poll it at appropriate moments.


    Wow, I learned a lot from this thread--many thanks, all. James, can
    you point me to how to create the signal handler thread that you
    describe? I think that I get it in principle, but am having a hard
    time imagining how to actually do it.

    Again, many thanks,
    Craig
    Dudebot, Dec 30, 2010
    #10
  11. Dudebot

    Ian Collins Guest

    On 12/31/10 06:27 AM, Dudebot wrote:
    > On Dec 30, 5:33 am, James Kanze<> wrote:
    >
    >> More generally, you probably don't want to, at least if the goal
    >> is to trigger a clean shutdown. You normally can't start
    >> a clean shutdown at just anytime, and signals arrive
    >> asynchronously. The usual solution depends on the application:
    >> for anything multithreaded under Unix, you can create a special
    >> signal handler thread; signals will generate an event which
    >> unblocks the thread, and the thread can start the clean shutdown
    >> (running as a normal thread, and not as a signal handler). For
    >> single threaded processes, the usual solution is just to have
    >> a global sig_atomic_t initialized to zero, set it to one in the
    >> signal handler, and poll it at appropriate moments.

    >
    > Wow, I learned a lot from this thread--many thanks, all. James, can
    > you point me to how to create the signal handler thread that you
    > describe? I think that I get it in principle, but am having a hard
    > time imagining how to actually do it.


    This is drifting into the realm of comp.programming.threads, but it's
    really quite simple. You just create a thread that blocks on sigwait()
    and mask out signals to the other threads. The Solaris man page has an
    example:

    http://docs.sun.com/app/docs/doc/816-5167/sigwait-2?l=en&n=1&a=view

    --
    Ian Collins
    Ian Collins, Dec 30, 2010
    #11
  12. Dudebot

    James Kanze Guest

    On Dec 30, 7:23 pm, Ian Collins <> wrote:
    > On 12/31/10 06:27 AM, Dudebot wrote:
    > > On Dec 30, 5:33 am, James Kanze<> wrote:


    > >> More generally, you probably don't want to, at least if the goal
    > >> is to trigger a clean shutdown. You normally can't start
    > >> a clean shutdown at just anytime, and signals arrive
    > >> asynchronously. The usual solution depends on the application:
    > >> for anything multithreaded under Unix, you can create a special
    > >> signal handler thread; signals will generate an event which
    > >> unblocks the thread, and the thread can start the clean shutdown
    > >> (running as a normal thread, and not as a signal handler). For
    > >> single threaded processes, the usual solution is just to have
    > >> a global sig_atomic_t initialized to zero, set it to one in the
    > >> signal handler, and poll it at appropriate moments.


    > > Wow, I learned a lot from this thread--many thanks, all. James, can
    > > you point me to how to create the signal handler thread that you
    > > describe? I think that I get it in principle, but am having a hard
    > > time imagining how to actually do it.


    > This is drifting into the realm of comp.programming.threads, but it's
    > really quite simple. You just create a thread that blocks on sigwait()
    > and mask out signals to the other threads. The Solaris man page has an
    > example:


    > http://docs.sun.com/app/docs/doc/816-5167/sigwait-2?l=en&n=1&a=view


    And the example only uses Posix functionality---no Solaris
    extensions---so it should port easily to most other Linux
    platforms. (Not that I can easily verify it at the moment.)

    --
    James Kanze
    James Kanze, Dec 30, 2010
    #12
    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. Michael Pronath
    Replies:
    1
    Views:
    1,166
    Diez B. Roggisch
    Jan 3, 2005
  2. Jack Orenstein

    threading.Thread vs. signal.signal

    Jack Orenstein, Sep 18, 2005, in forum: Python
    Replies:
    0
    Views:
    463
    Jack Orenstein
    Sep 18, 2005
  3. Weng Tianxiang
    Replies:
    2
    Views:
    658
    Jonathan Bromley
    Jan 30, 2007
  4. Nicolas Moreau
    Replies:
    9
    Views:
    3,140
  5. dibacco73
    Replies:
    1
    Views:
    647
    joris
    Feb 12, 2009
Loading...

Share This Page