Определить остановку системы в с ++ - PullRequest
0 голосов
/ 06 февраля 2012

Хорошо, я работаю над программой, написанной на c ++, которая работает как демон.Он в первую очередь нацелен на пользователей Linux, но я хочу включить пользователей Windows (работающих в качестве службы) и Mac.

Я хочу, чтобы демон регистрировал журнал всякий раз, когда он выключается вручную.Однако он должен не регистрировать отключения, сделанные системой из-за остановки или перезагрузки системы.

В настоящее время я замаскировал все сигналы и реализовал некоторую обработку с помощью sigaction ().Перед регистрацией завершения работы функция также проверяет уровень запуска системы, и, если оно равно 0, 1 0r 6, регистрация не производится.Чтобы проверить уровень запуска, нужно запустить команду «уровень запуска» и обработать вывод.

Моя проблема в том, что уровень запуска не всегда соответствует ожидаемому.Я использую Ubuntu, и когда я вхожу в систему как обычно, я на уровне запуска 2, и это то же самое при перезагрузке.При остановке я иногда ничего не получаю в качестве вывода из "runlevel".Различные дистрибутивы Linux используют свои собственные уровни запуска, поэтому он не оптимален для переносимости.

Так есть ли лучший способ определить, останавливается ли система?Кроме того, есть ли лучший способ отловить прерывания, например, с помощью обработки исключений и т. Д.

Я вставлю фрагмент кода, если он поможет.Написан на c ++ с использованием библиотек Poco C ++ .

void MainApplication::signalHandler(int sig) {
#if defined(POCO_OS_FAMILY_UNIX)
    switch(sig) {
        case -1:
            struct sigaction act;
            act.sa_handler = signalHandler;
            sigemptyset(&act.sa_mask);
            act.sa_flags = 0;
            sigaction(SIGINT, &act, 0); //Better way to do this?
            sigaction(SIGQUIT, &act, 0);
            sigaction(SIGKILL, &act, 0);
            sigaction(SIGTERM, &act, 0);
            sigaction(SIGHUP, &act, 0);
            sigaction(SIGSTOP, &act, 0);
            sigaction(SIGTSTP, &act, 0);
            sigaction(SIGCONT, &act, 0);
            sigaction(SIGUSR1, &act, 0);
            sigaction(SIGUSR2, &act, 0);
            break;
        case SIGINT:
        case SIGQUIT:
        case SIGTSTP:
        case SIGHUP:
        case SIGKILL:
        case SIGTERM:
            //Log Shutdown!
            if (!isHalting())
                _instance->_database->logBypass(BYPASS_SHUTDOWN);
            terminateNicely(true);
            break;
        case SIGCONT:
            //Continued, means stopped
            break;
        case SIGUSR1:
            //Resetting Net Responsibility
            _instance->uninitialize();
            _instance->initialize(*_instance);
            break;
        case SIGUSR2:
            //Other action or just mask it
            break;
        default:
            //Caught signal
            break;
    }
#endif
}



bool MainApplication::isHalting() {
#if defined(POCO_OS_FAMILY_UNIX)
    string cmd("runlevel");
    vector<string> args;
    Poco::Pipe outPipe;
    ProcessHandle ph = Process::launch(cmd, args, 0, &outPipe, 0);
    ph.wait();
    Poco::PipeInputStream istr(outPipe);
    stringstream ss;
    Poco::StreamCopier::copyStream(istr, ss);
    int runlevel;
    ss.seekg(-2, ios::end);
    ss >> runlevel;
    return (runlevel == 0 || runlevel == 1 || runlevel == 6);
#else
    return false;
#endif
}

1 Ответ

0 голосов
/ 28 июня 2012

Я решил пойти другим путем, чтобы решить проблему.Сейчас я читаю историю загрузки компьютера и сравниваю ее с историей программного обеспечения, чтобы увидеть, загружался ли компьютер или остановился без программного обеспечения.Этого достаточно и, вероятно, будет еще более точным.

Команда, используемая для определения истории загрузки в Linux:

$ last reboot
...