3

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?

Bruno Bieri
  • 9,724
  • 11
  • 63
  • 92
bxshi
  • 2,252
  • 5
  • 31
  • 50

1 Answers1

3

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;
}
Craig Estey
  • 30,627
  • 4
  • 24
  • 48