Обработка прерываний с помощью нестатической функции-члена

Я пытаюсь выполнить обработку прерывания с помощью функции-члена из класса.

Код

signal(SIGABRT, socketServer.signalHandler);

где определение signalHandler

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

Когда я компилирую код, я получаю сообщение об ошибке

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

Я пытаюсь захватить SIGABRT с помощью этой функции signalHandler, очистить и остановить экземпляр socketServer. Я думаю, что могу использовать глобальную переменную и глобальную функцию для выполнения этой работы, но есть мысли о том, чтобы сделать это с помощью функции-члена?


person bxshi    schedule 15.12.2015    source источник
comment
Связанный вопрос: stackoverflow.com/q/343219/1340631   -  person scai    schedule 25.07.2017


Ответы (1)


Нет, вы не можете не этого делать.

Причина в том, что все функции member имеют "подразумеваемый/скрытый" аргумент указателя this. Если бы мы «сгладили» ваше определение обработчика, чтобы создать эквивалент C, это выглядело бы так:

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

Функция signal [в C] ничего об этом не знает [каламбур]. Если бы он скомпилировался, обработчик был бы вызван с sig в аргументе this, а не в аргументе sig.

Итак, вы действительно должны сделать:

SocketServer my_global_server;

void
my_handler(int sig)
{

    my_global_server.signalHandler(sig);
}

int
main(void)
{

    signal(SIGABRT,my_handler);

    return 0;
}

На самом деле вышеописанное весьма опасно, потому что my_global_server может находиться в неопределенном состоянии, когда вызывается обработчик сигнала, вызывая UB. Кроме того, когда вы находитесь в обработчике сигналов, вам разрешено делать ограниченное количество вещей. Например, никаких операций с кучей не разрешено.

Вот лучший способ реализовать это:

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;
}
person Craig Estey    schedule 15.12.2015