Чтение общих данных внутри обработчика сигнала - PullRequest
9 голосов
/ 13 декабря 2011

Я нахожусь в ситуации, когда мне нужно прочитать двоичное дерево поиска (BST) внутри обработчика сигнала (обработчик сигнала SIGSEGV , который, насколько мне известно, основан на базе каждого потока). BST может быть изменен другими потоками в приложении.

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

Ответы [ 4 ]

4 голосов
/ 02 декабря 2012

Я вижу два совершенно чистых решения:

  1. Для Linux: создайте выделенный поток для обработки сигналов.Ловите сигналы, используя signalfd () .Таким образом, вы будете обрабатывать сигналы в обычном потоке, а не в каком-либо ограниченном обработчике.
  2. Переносимый: также используйте выделенный поток, который спит, пока не будет получен сигнал.Вы можете использовать канал для создания пары файловых дескрипторов.Поток может прочитать (2) из ​​первого дескриптора, а в обработчике сигнала вы можете записать (2) во второй дескриптор.Использование write () в обработчике сигналов допустимо в соответствии с POSIX .Когда поток читает что-то из канала, он знает, что должен выполнить какое-то действие.
4 голосов
/ 13 декабря 2011

Вы не должны получать доступ к общим данным из обработчика сигнала. Вы можете узнать больше информации о сигналах в следующих статьях:

Сигналы Linux для прикладного программиста

Модель обработки сигналов Linux

Все о сигналах Linux

Похоже, самый безопасный способ обработки сигналов в linux - это signalfd.

3 голосов
/ 13 декабря 2011

Предполагая, что SH не может получить доступ к совместно используемым данным напрямую, тогда, возможно, вы могли бы сделать это косвенно:

  1. Иметь некоторую глобальную переменную, в которую могут записывать только обработчики сигналов, но которые могут быть прочитаны из других источников.(даже если только внутри одного потока).
  2. SH устанавливает флаг, когда он вызывается
  3. Потоки опрашивают этот флаг, когда они не находятся в середине изменения BST;когда он найден, он выполняет обработку, которая требуется исходному сигналу (используя любые необходимые синхронизации), а затем выдает другой сигнал (например, SIGUSR1), чтобы указать, что обработка выполнена
  4. SHдля сигнала TH сбрасывает флаг

Если вы беспокоитесь о перекрывающихся SIGSEGV, добавьте счетчик к миксу для отслеживания.(Эй! Вы только что создали свой собственный семафор!)

Слабым звеном здесь, очевидно, является опрос, но это начало.

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

Вы могли бы рассмотреть mmap -ing fuse файловую систему (в пространстве пользователя).

На самом деле, вы будете более счастливы от GnuHurd , который имеет поддержку внешних пейджеров

И, возможно, ваш хак с чтением бинарного дерева поиска в вашем обработчике сигналов может часто работать на практике, не переносимо и в версии ядразависимый путь.Возможно, сериализация доступа с низкоуровневыми непереносимыми приемами (например, futexes и встроенные атомарные gcc ) может работать.Чтение (машинно-зависимого) исходного кода NPTL, т. Е. Текущих подпрограмм Linux pthread, должно помочь.

Вероятно, это тот случай, когда pthread_mutex_lock и т. Д. Фактически могут использоваться из обработчика сигналов Linux ... (потому чтоон, вероятно, делает только futex и атомарные инструкции).

...