Spec-Zone.ru › Ruby 2.6

Ограничения при реализации обратных вызовов Signal.trap

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

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

Детали реализации виртуальной машины Ruby

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

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

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

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

  • Dir.chdir с блоком

  • любые операции записи в IO, когда IO#sync равно false; включая 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 может использоваться для обхода невозможности использования мьютексов внутри обработчика сигналов

  • 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–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

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