How to play with C callbacks (signal()) using C++ instance methods.

Discussion in 'C++' started by Daniel Koch, Nov 26, 2008.

  1. Daniel Koch

    Daniel Koch Guest

    Great people,

    I've a doubt about POSIX C functions when I'm using with C++.

    I need to handle a signal, the signal() from signal.h needs a
    callback. This callback need to perform an action inside class.

    How can I define this callback as my instance method?

    I think the wrong way is to define a pointer to class instance (this)
    as global, then I can call public methods of class from this callback
    (the callback defined by signal() haven't a void pointer to pass an
    instance pointer).

    What's the right way to do this?

    Thank you,
    Daniel Koch
     
    Daniel Koch, Nov 26, 2008
    #1
    1. Advertising

  2. Re: How to play with C callbacks (signal()) using C++ instancemethods.

    On Nov 26, 5:01 pm, Daniel Koch <> wrote:

    > I've a doubt about POSIX C functions when I'm using with C++.
    >
    > I need to handle a signal, the signal() from signal.h needs a
    > callback. This callback need to perform an action inside class.
    >
    > How can I define this callback as my instance method?
    >
    > I think the wrong way is to define a pointer to class instance (this)
    > as global, then I can call public methods of class from this callback
    > (the callback defined by signal() haven't a void pointer to pass an
    > instance pointer).


    You would need a global object.

    > What's the right way to do this?


    There is a deeper problem: from within a signal handler you can call
    only a limited set of functions, see the complete function list
    http://www.opengroup.org/onlinepubs/000095399/functions/xsh_chap02_04.html#tag_02_04_03.

    Popular functions like malloc() (and C++ new), all C stdio (and C++
    IOStreams) and all pthread functions are not async-signal safe.

    A standard way to deal with signals is the self-pipe trick, where a
    signal handler writes a byte to a pipe whose other end is monitored by
    select() in the main program. With new Linux kernels you can do
    better: http://www.kernel.org/doc/man-pages/online/pages/man2/signalfd.2.html

    This way your signals end up being file descriptor events, which you
    can redirect easily to member functions.

    Another way is to block signals in all threads and spawn a thread
    which would wait for signals using sigwait() and handle signals
    synchronously in that thread only.

    --
    Max
     
    Maxim Yegorushkin, Nov 26, 2008
    #2
    1. Advertising

  3. Daniel Koch

    James Kanze Guest

    Re: How to play with C callbacks (signal()) using C++ instancemethods.

    On Nov 26, 6:01 pm, Daniel Koch <> wrote:
    > I've a doubt about POSIX C functions when I'm using with C++.


    > I need to handle a signal, the signal() from signal.h needs a
    > callback. This callback need to perform an action inside
    > class.


    You can't do that from a signal handler, at least not reliably.

    > How can I define this callback as my instance method?


    You can't.

    > I think the wrong way is to define a pointer to class instance
    > (this) as global, then I can call public methods of class from
    > this callback (the callback defined by signal() haven't a void
    > pointer to pass an instance pointer).


    Even that's not guaranteed to work. The relevant standards (C,
    C++ and Posix) don't even allow you to read a pointer, much less
    do anything with it.

    > What's the right way to do this?


    Do what? The usual way of associating complex actions with a
    signal under Posix is to use a signal handling thread, using
    sigaction to block the signals in all of the other threads, and
    sigwait in the signal handling thread. This should all be
    described in your books on Unix programming (and since it is so
    Unix specific, if you have further questions, you should ask in
    a Unix group).

    --
    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, Nov 26, 2008
    #3
  4. Daniel Koch

    Daniel Koch Guest

    Re: How to play with C callbacks (signal()) using C++ instancemethods.

    On 26 nov, 16:24, James Kanze <> wrote:
    > On Nov 26, 6:01 pm, Daniel Koch <> wrote:
    >
    > > I've a doubt about POSIX C functions when I'm using with C++.
    > > I need to handle a signal, the signal() from signal.h needs a
    > > callback. This callback need to perform an action inside
    > > class.

    >
    > You can't do that from a signal handler, at least not reliably.
    >
    > > How can I define this callback as my instance method?

    >
    > You can't.
    >
    > > I think the wrong way is to define a pointer to class instance
    > > (this) as global, then I can call public methods of class from
    > > this callback (the callback defined by signal() haven't a void
    > > pointer to pass an instance pointer).

    >
    > Even that's not guaranteed to work.  The relevant standards (C,
    > C++ and Posix) don't even allow you to read a pointer, much less
    > do anything with it.
    >
    > > What's the right way to do this?

    >
    > Do what?  The usual way of associating complex actions with a
    > signal under Posix is to use a signal handling thread, using
    > sigaction to block the signals in all of the other threads, and
    > sigwait in the signal handling thread.  This should all be
    > described in your books on Unix programming (and since it is so
    > Unix specific, if you have further questions, you should ask in
    > a Unix group).
    >
    > --
    > 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


    I've found Glib::SignalChildWatch.

    I'm using gtkmm to show some windows and it is using libsigc++,
    now I can use an instance method as signal handlers. :)

    Thank you.
    Daniel Koch
     
    Daniel Koch, Nov 26, 2008
    #4
  5. Daniel Koch wrote:
    > What's the right way to do this?


    Other people have written about it not being standard and not
    guaranteed to work and whatever, but I myself have used this many times
    with C callbacks in unix systems successfully.

    Most C callback mechanisms will take some data pointer as parameter,
    which they will then pass to the callback function. Simply give a
    pointer to the class instance as this data pointer, and as callback
    function create a function which will reinterpret-cast that void* to the
    class type and call the proper member function.

    For example, assume you have some class like:

    class A
    {
    public:
    void callback();
    };


    You want to create an instance of A, and then have the C library
    callback end up calling that A::callbackFunction() for that instance.
    What you do is that you write a callback function with a signature
    expected by that C library, and inside it you just call the object:

    void callbackFunction(void* data)
    {
    A* obj = reinterpret_cast<A*>(data);
    obj->callback();
    }

    Then somewhere you tell the C library to call that function, like:

    cLibrarySetupCallbackFunction(callbackFunction, &obj);

    where 'obj' is that A instance which you want to be called.

    I have had this work like that. It *might* be possible that in some
    situation you'll have to surround that callbackFunction with extern "C".

    Sure, there might be *some* architectures and compilers where this
    won't work, but I have had it working at least with gcc in a Sparc
    Solaris as well as a PC Linux system.
     
    Juha Nieminen, Nov 27, 2008
    #5
  6. Daniel Koch

    James Kanze Guest

    Re: How to play with C callbacks (signal()) using C++ instancemethods.

    On Nov 27, 11:44 pm, Juha Nieminen <> wrote:
    > Daniel Koch wrote:
    > > What's the right way to do this?


    > Other people have written about it not being standard and not
    > guaranteed to work and whatever, but I myself have used this
    > many times with C callbacks in unix systems successfully.


    > Most C callback mechanisms will take some data pointer as
    > parameter, which they will then pass to the callback function.


    Did you read his question? He was concerned doing something
    from a signal handler. It's not just any callback; signal
    handlers run under very special conditions. And of course, they
    *don't* take a data pointer which will be passed back to the
    handler.

    [...]
    > You want to create an instance of A, and then have the C
    > library callback end up calling that A::callbackFunction() for
    > that instance. What you do is that you write a callback
    > function with a signature expected by that C library, and
    > inside it you just call the object:


    > void callbackFunction(void* data)
    > {
    > A* obj = reinterpret_cast<A*>(data);
    > obj->callback();
    > }


    > Then somewhere you tell the C library to call that function, like:
    >
    > cLibrarySetupCallbackFunction(callbackFunction, &obj);


    > where 'obj' is that A instance which you want to be called.


    This is fine for most callbacks, except that you have to declare
    callbackFunction ``extern "C"''.

    > I have had this work like that. It *might* be possible that in
    > some situation you'll have to surround that callbackFunction
    > with extern "C".


    The "situation" where you'd have to use ``extern "C"'' is
    simple: any time the compiler isn't broken.

    > Sure, there might be *some* architectures and compilers where
    > this won't work, but I have had it working at least with gcc
    > in a Sparc Solaris as well as a PC Linux system.


    This is a known bug in g++. Sun CC will diagnose an error
    without the ``extern "C"''.

    --
    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, Nov 28, 2008
    #6
  7. Re: How to play with C callbacks (signal()) using C++ instancemethods.

    On Nov 27, 10:44 pm, Juha Nieminen <> wrote:
    > Daniel Koch wrote:
    > > What's the right way to do this?

    >
    >   Other people have written about it not being standard and not
    > guaranteed to work and whatever, but I myself have used this many times
    > with C callbacks in unix systems successfully.
    >
    >   Most C callback mechanisms will take some data pointer as parameter,
    > which they will then pass to the callback function. Simply give a
    > pointer to the class instance as this data pointer, and as callback
    > function create a function which will reinterpret-cast that void* to the
    > class type and call the proper member function.


    static_cast<> is sufficient when casting from void* to T*.

    --
    Max
     
    Maxim Yegorushkin, Nov 28, 2008
    #7
  8. Re: How to play with C callbacks (signal()) using C++ instancemethods.

    On Nov 28, 8:32 am, James Kanze <> wrote:
    > On Nov 27, 11:44 pm, Juha Nieminen <> wrote:


    []

    > > cLibrarySetupCallbackFunction(callbackFunction, &obj);
    > > where 'obj' is that A instance which you want to be called.

    >
    > This is fine for most callbacks, except that you have to declare
    > callbackFunction ``extern "C"''.
    >
    > > I have had this work like that. It *might* be possible that in
    > > some situation you'll have to surround that callbackFunction
    > > with extern "C".

    >
    > The "situation" where you'd have to use ``extern "C"'' is
    > simple: any time the compiler isn't broken.
    >
    > > Sure, there might be *some* architectures and compilers where
    > > this won't work, but I have had it working at least with gcc
    > > in a Sparc Solaris as well as a PC Linux system.

    >
    > This is a known bug in g++.  Sun CC will diagnose an error
    > without the ``extern "C"''.


    C and C++ calling conventions have been the same on Solaris. I don't
    think Sun will ever change it because their remaining customers are
    not going to be happy.

    While formally it might make sense to emit this error, it is
    practically useless.

    --
    Max
     
    Maxim Yegorushkin, Nov 28, 2008
    #8
  9. Daniel Koch

    James Kanze Guest

    Re: How to play with C callbacks (signal()) using C++ instancemethods.

    On Nov 28, 10:42 am, Maxim Yegorushkin <>
    wrote:
    > On Nov 28, 8:32 am, James Kanze <> wrote:


    [...]
    > C and C++ calling conventions have been the same on Solaris. I
    > don't think Sun will ever change it because their remaining
    > customers are not going to be happy.


    > While formally it might make sense to emit this error, it is
    > practically useless.


    It's required by the standard. A compiler which doesn't emit
    the error isn't conform. The fact that the calling conventions
    happen to be the same isn't really relevant; the language allows
    them to be different, and considers them different types.

    --
    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, Nov 28, 2008
    #9
  10. Re: How to play with C callbacks (signal()) using C++ instancemethods.

    On Nov 28, 2:25 pm, James Kanze <> wrote:
    > On Nov 28, 10:42 am, Maxim Yegorushkin <>
    > wrote:
    >
    > > On Nov 28, 8:32 am, James Kanze <> wrote:

    >
    >     [...]
    >
    > > C and C++ calling conventions have been the same on Solaris. I
    > > don't think Sun will ever change it because their remaining
    > > customers are not going to be happy.
    > > While formally it might make sense to emit this error, it is
    > > practically useless.

    >
    > It's required by the standard.  A compiler which doesn't emit
    > the error isn't conform.  The fact that the calling conventions
    > happen to be the same isn't really relevant; the language allows
    > them to be different, and considers them different types.


    Is there a platform/compiler where they are different?

    --
    Max
     
    Maxim Yegorushkin, Nov 28, 2008
    #10
  11. Daniel Koch

    James Kanze Guest

    Re: How to play with C callbacks (signal()) using C++ instancemethods.

    On Nov 28, 3:48 pm, Maxim Yegorushkin <>
    wrote:
    > On Nov 28, 2:25 pm, James Kanze <> wrote:
    > > On Nov 28, 10:42 am, Maxim Yegorushkin
    > > <> wrote:
    > > > On Nov 28, 8:32 am, James Kanze <> wrote:


    > >     [...]
    > > > C and C++ calling conventions have been the same on
    > > > Solaris. I don't think Sun will ever change it because
    > > > their remaining customers are not going to be happy.
    > > > While formally it might make sense to emit this error, it
    > > > is practically useless.


    > > It's required by the standard.  A compiler which doesn't emit
    > > the error isn't conform.  The fact that the calling conventions
    > > happen to be the same isn't really relevant; the language allows
    > > them to be different, and considers them different types.


    > Is there a platform/compiler where they are different?


    There certainly have been; there are very strong reasons for
    making them different on an Intel, for example, and they were
    different on the first C++ compiler I used. (I'm not too sure
    what the situation is with VC++ today; I think it uses some
    non-standard means, but the results are the same.)

    --
    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, Nov 28, 2008
    #11
  12. Re: How to play with C callbacks (signal()) using C++ instancemethods.

    On Nov 28, 7:25 pm, James Kanze <> wrote:
    > On Nov 28, 3:48 pm, Maxim Yegorushkin <>
    > wrote:
    >
    > > On Nov 28, 2:25 pm, James Kanze <> wrote:
    > > > On Nov 28, 10:42 am, Maxim Yegorushkin
    > > > <> wrote:
    > > > > On Nov 28, 8:32 am, James Kanze <> wrote:
    > > >     [...]
    > > > > C and C++ calling conventions have been the same on
    > > > > Solaris. I don't think Sun will ever change it because
    > > > > their remaining customers are not going to be happy.
    > > > > While formally it might make sense to emit this error, it
    > > > > is practically useless.
    > > > It's required by the standard.  A compiler which doesn't emit
    > > > the error isn't conform.  The fact that the calling conventions
    > > > happen to be the same isn't really relevant; the language allows
    > > > them to be different, and considers them different types.

    > > Is there a platform/compiler where they are different?

    >
    > There certainly have been; there are very strong reasons for
    > making them different on an Intel, for example, and they were
    > different on the first C++ compiler I used.  (I'm not too sure
    > what the situation is with VC++ today; I think it uses some
    > non-standard means, but the results are the same.)


    Any present day examples?

    --
    Max
     
    Maxim Yegorushkin, Dec 1, 2008
    #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. Neo
    Replies:
    1
    Views:
    550
    Scott Allen
    Jan 7, 2005
  2. johny smith

    instance based callbacks

    johny smith, May 14, 2004, in forum: C++
    Replies:
    2
    Views:
    341
    David White
    May 14, 2004
  3. John M. Gabriele
    Replies:
    18
    Views:
    1,225
    Steven Bethard
    Feb 18, 2005
  4. Leon Bogaert
    Replies:
    19
    Views:
    360
    Robert Klemme
    Mar 23, 2008
  5. Kenneth McDonald
    Replies:
    5
    Views:
    387
    Kenneth McDonald
    Sep 26, 2008
Loading...

Share This Page