Как обрабатывать длительные вызовы внешних функций, такие как блокировка ввода-вывода в Rust?
Примечание редактора: Этот вопрос относится к версии Rust до 1.0 и использует термины и функции, которых нет в коде Rust 1.0. Выраженные концепции по-прежнему актуальны.
Мне нужно прочитать данные, предоставленные внешним процессом через дескриптор файла POSIX в моей программе Rust. Соединение с файловым дескриптором поддерживается очень долго (часы), и другая сторона время от времени передает мне данные. Мне нужно читать и обрабатывать поток данных непрерывно.
Для этого я написал цикл, который вызывает libc::read()
(фактически readv
) для чтения данных и их обработки при получении. Так как это блокирует весь планировщик, я порождаю задачу в новом планировщике (task::spawn_sched(SingleThreaded)
). Это работает нормально, пока он работает, но я не могу найти способ аккуратно отключить цикл.
Поскольку цикл блокирует большую часть времени, я не могу использовать порт/канал, чтобы уведомить цикл о выходе.
Я попытался убить задачу цикла, сняв ее с помощью сбойной связанной задачи (создать задачу цикла под наблюдением, создать связанную задачу внутри нее и дождаться сигнала на порте, прежде чем произойдет fail!()
Вызывая и отключая цикл Задача с ним). Он хорошо работает в тестах, но libc::read()
не прерывается (задача не завершается неудачей, пока чтение не завершается, и через некоторое время она достигает task::yield()
.
Я многому научился, глядя на исходники libcore, но, похоже, не могу найти правильного решения.
- Есть ли способ убить (дочернюю) задачу в Rust, даже если она выполняет какой-то длинный внешний вызов функции, такой как блокирующее чтение?
- Есть ли способ сделать неблокирующее чтение для файлового дескриптора POSIX, чтобы Rust сохранял контроль над задачей?
- Как я могу реагировать на сигналы, например,
SIGTERM
если пользователь завершает мою программу? Кажется, в Rust пока что нет ничего похожего на sigaction()
.
Ответы
Ответ 1
- Согласно mozila, убить задачу уже невозможно, на данный момент, не говоря уже о блокировании чтения.
- Это можно сделать после
mozilla/rust/pull/11410
, см. также мой другой отчет о проблеме для rust-zmq erickt/rust-zmq/issues/24
, который также зависит от этого. (извините за ссылки)
- Может быть, прослушиватель сигналов будет работать для вас.
Ответ 2
Есть ли способ убить (дочернюю) задачу в Rust, даже если она выполняет какой-то длинный внешний вызов функции, такой как блокирующее чтение?
Нет.
Смотрите также:
Есть ли способ сделать неблокирующее чтение [...] так, чтобы Rust сохранял контроль над задачей?
Да.
Смотрите также:
на дескриптор файла POSIX
Да.
Смотрите также:
Как я могу реагировать на сигналы
Выберите нужную платформу для поддержки, затем выберите подходящий ящик.
Смотрите также: