Spec-Zone.ru › Ruby 2.7

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

  • 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