Рекомендации по восстановлению после сбоя сегментации

Я работаю над многопоточным процессом, написанным на С++, и рассматриваю модификацию обработки SIGSEGV с помощью google-coredumper, чтобы сохранить процесс в живых, когда возникает ошибка сегментации.

Тем не менее, это использование google-coredumper похоже на то, что у вас есть возможность застревать в бесконечном цикле дампов ядра, если я каким-то образом не инициализирую поток и объект, который мог вызвать основной дамп.

Какие лучшие практики следует иметь в виду при попытке сохранить процесс через ядро? С какими другими "пропахами" я должен знать?

Спасибо!

Ответ 1

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

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

Ответ 2

На самом деле это возможно в C. Вы можете достичь этого довольно сложным образом:

1) Обработчик сигнала переопределения

2) Используйте setjump() и longjmp(), чтобы установить место для перехода назад и фактически вернуться туда.

Проверьте этот код, который я написал (идея взята из "Expert C Programming: Deep C Secrets" Питера Ван Дер Линдена):

#include <signal.h>
#include <stdio.h>
#include <setjmp.h>

//Declaring global jmp_buf variable to be used by both main and signal handler
jmp_buf buf;


void magic_handler(int s)
{

    switch(s)
    {

        case SIGSEGV:
        printf("\nSegmentation fault signal caught! Attempting recovery..");
        longjmp(buf, 1);
        break;
    }

    printf("\nAfter switch. Won't be reached");

}



int main(void) 
{

    int *p = NULL;

    signal(SIGSEGV, magic_handler);

    if(!setjmp(buf))
    {

         //Trying to dereference a null pointer will cause a segmentation fault, 
         //which is handled by our magic_handler now.
         *p=0xdead;

    }
    else
    {
        printf("\nSuccessfully recovered! Welcome back in main!!\n\n"); 
    }



    return 0;
}

Ответ 3

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

Это по уважительной причине: вы действительно ожидаете, что память (которую ваши потоки разделяют) будет неповрежденной после SIGSEGV? В конце концов, вы только что доказали, что некоторая адресация нарушена, поэтому предположение, что остальная часть пространства памяти чиста, довольно оптимистична.

Подумайте о другой модели concurrency, например. с процессами. Процессы не делят свою память или только четко определенную часть (разделяемую память), и один процесс может разумно работать, когда другой процесс умер. Когда у вас есть критическая часть программы (например, контроль температуры ядра), добавление ее в дополнительный процесс защищает ее от повреждения памяти другими процессами и.

Ответ 4

Если произошла ошибка сегментации, вам лучше всего отбросить процесс. Как вы узнаете, что после этого можно использовать любую вашу память процесса? Если что-то в вашей программе возится с памятью, это не должно, почему вы считаете, что это не связано с какой-то другой частью памяти, к которой ваш процесс действительно может получить доступ без segfault?

Я думаю, что делать это в основном выгоду для злоумышленников.

Ответ 5

Стив ответ на самом деле очень полезная формула. Я использовал что-то подобное в сложном встроенном программном обеспечении, где в коде было по крайней мере одна ошибка SIGSEGV, которую мы не могли отслеживать по времени судна. До тех пор, пока вы можете reset, чтобы ваш код не имел никаких негативных последствий (утечка памяти или ресурсов), а ошибка не является чем-то, что вызывает бесконечный цикл, это может быть спасатель (хотя лучше исправить ошибку). FYI в нашем случае это был единственный поток.

Но что осталось, так это то, что как только вы восстановитесь с вашего обработчика сигнала, он не будет работать снова, если вы не разоблачите сигнал. Вот фрагмент кода для этого:

sigset_t signal_set;
...
setjmp(buf);
sigemptyset(&signal_set);
sigaddset(&signal_set, SIGSEGV); 
sigprocmask(SIG_UNBLOCK, &signal_set, NULL); 
// Initialize all Variables...

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

Ответ 6

Из описания coredumper кажется, что цель не то, что вы намереваетесь, а просто позволяете делать снимки памяти процесса.

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

И, да, как предложила парапура, еще лучше выяснить, что вызывает SIGSEGV и исправить его.