c++interruption

Interruption handling with non-static member function


I am trying to do interruption handling with a member function from a class.

The code is

signal(SIGABRT, socketServer.signalHandler);

where the definition of signalHandler is

public:
void SocketServer::signalHandler(int sig)
{
  logger.info("Receive SIG"+to_string(sig)+" Stopping server now...");
  stop();
}

When I compile the code, I got an error says

main.cpp:32:32: error: reference to non-static member function must be called
  signal(SIGABRT, socketServer.signalHandler);

I am trying to capture SIGABRT using this signalHandler function and to clean up and stop the socketServer instance. I guess I can use global variable and a global function to do the job, but any thoughts about doing this with a member function?


Solution

  • No, you can not do this.

    The reason is that all member functions have an "implied/hidden" this pointer argument. If we "flattened" out your handler definition to produce the C equivalent, it would look like:

    void SocketServer::signalHandler(SocketServer *this,int sig);
    

    The signal function [in C] knows nothing of this [pun intended]. If it compiled, the handler would be called with sig going into the this argument and not the sig argument.

    So, you really must do:

    SocketServer my_global_server;
    
    void
    my_handler(int sig)
    {
    
        my_global_server.signalHandler(sig);
    }
    
    int
    main(void)
    {
    
        signal(SIGABRT,my_handler);
    
        return 0;
    }
    

    Actually, the above is quite dangerous because my_global_server may be in an indeterminate state when the signal handler is called, causing UB. Also, when in a signal handler, there are a limited number of things you are permitted to do. For example, no heap manipulations are permitted.

    Here is a better way to implement this:

    volatile int signal_flag;
    
    SocketServer my_global_server;
    
    void
    my_handler(int sig)
    {
    
        signal_flag = sig;
    }
    
    int
    main(void)
    {
    
        signal(SIGABRT,my_handler);
    
        while (! signal_flag) {
            ...
        }
    
        my_global_server.signalHandler(signal_flag);
    
        return 0;
    }