Spec-Zone.ru › Ruby 3

Осторожность при реализации обратных вызовов Signal.trap

Как и при реализации обработчиков сигналов в C или большинстве других языков, весь код, переданный в Signal.trap, должен быть повторно вводимым. Если вы не знакомы с повторной вводимостью, вам необходимо ознакомиться с этим на Википедии или где-либо ещё, прежде чем читать остальную часть этого документа.

Самое главное, «безопасность потоков» не гарантирует повторной вводимости; и такие методы, как Mutex#lock и Mutex#synchronize, которые обычно используются для безопасности потоков, даже предотвращают повторную вводимость.

Деталь реализации Ruby VM

Ruby VM откладывает обратные вызовы Signal.trap до тех пор, пока не будет безопасно для его внутренних структур данных, но он не знает, когда безопасно для структур данных ВАШЕГО кода. Ruby реализует отложенную обработку сигналов путём регистрации коротких функций C с только функциями, безопасными при асинхронном обработке сигналов, в качестве обработчиков сигналов. Эти короткие функции C делают только необходимое для уведомления VM о выполнении обратных вызовов, зарегистрированных с помощью Signal.trap, позднее в основном потоке Ruby Thread.

Небезопасные методы для вызова в блоках Signal.trap

Если есть сомнения, считайте всё, что не указано ниже как безопасное, небезопасным.

  • Mutex#lock, Mutex#synchronize и любой код, использующий их, явно небезопасен. Это включает Monitor в стандартной библиотеке, которая использует Mutex для обеспечения повторной вводимости.

  • Dir.chdir с блоком

  • любые операции записи в IO, когда IO#sync ложно; включая IO#write, IO#write_nonblock, IO#puts. Трубы и сокеты по умолчанию имеют `IO#sync = true`, поэтому запись в них безопасна, если не было отключено IO#sync.

  • File#flock, так как вызов flock(2) в основе не определён POSIX

Обычно безопасные операции внутри блоков Signal.trap

  • Присваивание и получение локальных, экземпляра и класса переменных

  • Большинство выделений объектов и инициализаций общих типов, включая Array, Hash, String, Struct, Time.

  • Общие операции Array, Hash, String, Struct, которые не выполняют блок, как правило, безопасны; но будьте осторожны, если итерация происходит где-то ещё.

  • Hash#[], Hash#[]= (если Hash.new не был передан небезопасный блок)

  • Thread::Queue#push и Thread::SizedQueue#push (с Ruby 2.1)

  • Создание нового Thread через Thread.new/Thread.start может помочь обойти невозможность использования Mutexes внутри обработчика сигналов

  • Signal.trap безопасно использовать внутри блоков, переданных Signal.trap

  • Арифметические операции с Integer и Float (`+', `-', '%', '*', '/')

    Кроме того, обработчики сигналов не выполняются между двумя последовательными обращениями к локальным переменным, поэтому такие сокращения, как `+=' и `-=' не вызовут гонку данных при использовании с Integer и Float классами в обработчиках сигналов.

Методы-обертки системных вызовов, безопасные внутри Signal.trap

Поскольку Ruby имеет обертки вокруг многих функций C, безопасных при асинхронном обработке сигналов, соответствующие обертки для многих IO, File, Dir и Socket методов безопасны.

(Неполный список)

  • Dir.chdir (без аргумента блока)

  • Dir.mkdir

  • Dir.open

  • File#truncate

  • File.link

  • File.open

  • File.readlink

  • File.rename

  • File.stat

  • File.symlink

  • File.truncate

  • File.unlink

  • File.utime

  • IO#close

  • IO#dup

  • IO#fsync

  • IO#read

  • IO#read_nonblock

  • IO#stat

  • IO#sysread

  • IO#syswrite

  • IO.select

  • IO.pipe

  • Process.clock_gettime

  • Process.exit!

  • Process.fork

  • Process.kill

  • Process.pid

  • Process.ppid

  • Process.waitpid

…

Ruby Core © 1993–2020 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API