Печать обратной трассировки в обработчике сигналов - PullRequest
0 голосов
/ 13 марта 2019

У меня проблема с основным потоком синхронизации и обработчиком сигнала.

Давайте рассмотрим простой класс:

class StackPrinter
{
    public:
        StackPrinter* Instance()
        {
            // Implemented classic singleton
        }

    private:
        std::vector<void*> PrintBacktrace(pthread_t threadId)
        {
            guard(someMutex);

            std::vector<void*> stack;
            _backtrace = &stack[0];

            // set up signal

            // kill thread so the signal will be raised

            // synchronise this thread with signalHandler with select and read methods

            return stack;
        }

    void** _backtrace;

    void signalHander(int sigNumber)
    {
        backtrace(_backtrace);

        // synchronise this thread with PrintBactrace with write method
    }
}

Так что этот код обычно будет работать нормально: мы поднимаем сигнал,мы обрабатываем его в методе signalHandler -> уведомляем о завершении работы в методе signalHandler через функцию записи -> получаем это уведомление через функцию select с тайм-аутом и жизнь может продолжаться ... но что, если, например, этот поток (threadId) будет работать непрерывносостояние?

Я не буду вводить метод signalHandler, метод select () получит тайм-аут, но затем приложение завершит свою работу в методе PrintBactrace, возвращая пустой векторный стек, и мы не знаем, выиграл ли этот поток 'изменить его состояние, так что метод signalHandler будет выполнен в конце концов, когда, возможно, другой процесс получит экземпляр класса StackPrinter и попытается вызвать другой сигнал.Поэтому, наконец, другой процесс будет использовать массив _backtrace, когда первый все же захочет его использовать.

Пожалуйста, помните, что все, что используется в методе signalHandler, должно быть безопасным для асинхронного сигнала (http://man7.org/linux/man-pages/man7/signal-safety.7.html).

РЕДАКТИРОВАТЬ: На мгновение у меня возникла идея статической карты, где ключом будет поток, а значением может быть вектор. Поэтому я бы вырезал void ** backtrace и вставил его в функцию signalHandler, так что единственная работа с нимсостоит в том, чтобы получить обратную трассировку и поместить ее в карту. Если это закончится в обычное время, основной поток получит этот вектор с карты - если нет, никто никогда не получит эти данные. Предполагая, что эта ситуация редка, нет риска слишком большогоиспользованная память. Что вы думаете?

...