Ловля сигналов c ++ - PullRequest
       24

Ловля сигналов c ++

2 голосов
/ 21 декабря 2011

У меня есть пул потоков Boost, который я использую для выполнения определенных задач. У меня также есть класс Sensor, который имеет чисто виртуальную функцию doWork(int total) = 0;. Всякий раз, когда это запрашивается, мой основной процесс получает необходимый указатель датчика и сообщает пулу потоков выполнить Sensor::doWork(int total).

threadpool->schedule(boost::bind(&Sensor::doWork,this,123456));

Я динамически загружаю библиотеки типа Sensor, таким образом, я не могу контролировать, если кто-то еще имеет неправильное кодирование, которое приводит к SEGFAULTS и так далее. Так есть ли способ для меня (в моем основном процессе) обработать любые ошибки, выданные Sensor::doWork(int total), очистить поток, удалить этот объект датчика и уведомить консоль, что и где произошла ошибка?

Ответы [ 3 ]

2 голосов
/ 21 декабря 2011

Действительно, единственный способ устранить ошибку сегментации - это запустить Sensor::doWork в совершенно отдельном процессе .

В UNIX это включает использование fork (или некоторых других подобных средств), запуск Sensor::doWork в дочернем процессе и затем каким-то образом возвращение результатов в родительский процесс.

Я предполагаю, что аналогичные средства доступны в Windows.

РЕДАКТИРОВАТЬ: Я думал, что я немного конкретизирую некоторые вещи, которые вы можете сделать.

Решение № 1: вы можете работать с процессами так же, как и с потоками. Например, вы можете создать пул процессов, который будет находиться в цикле

  • Подождите, пока задача будет передана по каналу или очереди или подобному объекту
  • Выполнить задание
  • Возвращать результаты по каналу, очереди или подобному объекту

И поскольку вы выполняете задачи в других процессах, вы защищены от их сбоев. Основная трудность с этим решением - это общение между процессами; может быть, в этом поможет библиотека interprocess boost. В основном я делал подобные вещи в python, который имеет стандартный модуль multiprocessing, который обрабатывает эти вещи для вас.

Решение № 2: Вы можете разделить ваше приложение на «безопасные» и «рискованные» части, которые работают в разных процессах. В «рискованной» части выполняются методы Sensor::doWork и все остальное, что вы, возможно, захотите сделать в этом процессе, - но только та работа, которая допустима, если она самопроизвольно теряется в случае сбоя. «Безопасная» часть имеет дело с любой ценной информацией, которую вы не можете позволить себе потерять, и отслеживает «рискованную» часть, выполняя некоторые операции восстановления после сбоя ребенка. И, конечно, любую другую работу, которую вы решите выполнять в безопасной части.

1 голос
/ 21 декабря 2011

Если вы получили SIGSEGV, даже если вы его поймали, у вас нет никаких гарантий относительно состояния вашей программы, поэтому практически невозможно восстановить.

Если вы работаете со сторонними библиотеками, иони глючат, и сопровождающий библиотеки не исправит это (и у вас нет исходного кода), тогда ваш единственный выход - запустить стороннюю библиотеку из совершенно отдельного двоичного файла, который каким-то образом общается с главным двоичным файлом,См. Например, firefox и плагин-контейнер.

0 голосов
/ 21 декабря 2011

Возможно, вы захотите зарегистрировать функцию обратного вызова, чтобы поймать SIGSEV.В C это может быть сделано с использованием сигнала .Имейте в виду, однако, что вы ничего не можете сделать, когда ОС отправляет вам SIGSEV (обратите внимание, что это не требуется).Думаю, вы не знаете, в каком состоянии находится ваша программа.Например, если куча повреждена, новые операции и операции удаления могут завершиться неудачей, поэтому даже простой простой оператор

 std::cout << std::string("hello world") << std::endl; 

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

Лучший, Кристоф

...