Как обрабатывать длительные вызовы внешних функций, такие как блокировка ввода-вывода в Rust?

Примечание редактора: Этот вопрос относится к версии Rust до 1.0 и использует термины и функции, которых нет в коде Rust 1.0. Выраженные концепции по-прежнему актуальны.

Мне нужно прочитать данные, предоставленные внешним процессом через дескриптор файла POSIX в моей программе Rust. Соединение с файловым дескриптором поддерживается очень долго (часы), и другая сторона время от времени передает мне данные. Мне нужно читать и обрабатывать поток данных непрерывно.

Для этого я написал цикл, который вызывает libc::read() (фактически readv) для чтения данных и их обработки при получении. Так как это блокирует весь планировщик, я порождаю задачу в новом планировщике (task::spawn_sched(SingleThreaded)). Это работает нормально, пока он работает, но я не могу найти способ аккуратно отключить цикл.

Поскольку цикл блокирует большую часть времени, я не могу использовать порт/канал, чтобы уведомить цикл о выходе.

Я попытался убить задачу цикла, сняв ее с помощью сбойной связанной задачи (создать задачу цикла под наблюдением, создать связанную задачу внутри нее и дождаться сигнала на порте, прежде чем произойдет fail!() Вызывая и отключая цикл Задача с ним). Он хорошо работает в тестах, но libc::read() не прерывается (задача не завершается неудачей, пока чтение не завершается, и через некоторое время она достигает task::yield().

Я многому научился, глядя на исходники libcore, но, похоже, не могу найти правильного решения.

  1. Есть ли способ убить (дочернюю) задачу в Rust, даже если она выполняет какой-то длинный внешний вызов функции, такой как блокирующее чтение?
  2. Есть ли способ сделать неблокирующее чтение для файлового дескриптора POSIX, чтобы Rust сохранял контроль над задачей?
  3. Как я могу реагировать на сигналы, например, SIGTERM если пользователь завершает мою программу? Кажется, в Rust пока что нет ничего похожего на sigaction().

Ответ 1

  • Согласно mozila, убить задачу уже невозможно, на данный момент, не говоря уже о блокировании чтения.
  • Это можно сделать после mozilla/rust/pull/11410, см. также мой другой отчет о проблеме для rust-zmq erickt/rust-zmq/issues/24, который также зависит от этого. (извините за ссылки)
  • Может быть, прослушиватель сигналов будет работать для вас.

Ответ 2

Есть ли способ убить (дочернюю) задачу в Rust, даже если она выполняет какой-то длинный внешний вызов функции, такой как блокирующее чтение?

Нет.

Смотрите также:

Есть ли способ сделать неблокирующее чтение [...] так, чтобы Rust сохранял контроль над задачей?

Да.

Смотрите также:

на дескриптор файла POSIX

Да.

Смотрите также:

Как я могу реагировать на сигналы

Выберите нужную платформу для поддержки, затем выберите подходящий ящик.

Смотрите также: