Прерванные команды процесса tokio и отключение unix процессов - PullRequest
0 голосов
/ 27 мая 2020

Я использую tokio 0.2.21 и futures 0.3.5 и rust c stable 1.43.1

Я использую futures :: future :: Abortable для обертывания tokio :: process: : Команда, чтобы я мог прервать процесс из другой задачи tokio.

Я понимаю, что:

Unix требует, чтобы родители процесса подтвердили завершение дочернего процесса одним из нескольких механизмы. tokio :: process :: unix :: Child был изменен таким образом, что при удалении экземпляра вызывается kill (), которая убивает дочерний процесс, но не вызывает try_wait или wait, поскольку эти вызовы могут блокировать. Была создана глобальная очередь процессов, которые нужно "пожать" путем вызова try_wait.

Что у меня есть псевдо-код sh -код:

async fn do_work() {
    // Spawn the child command
    let child = Command::new("sleep").args(&["30"]).spawn();

    // Move the child in to a future that waits for the child to complete and is wrapped in an Abortable
    let (abort_handle, abort_registration) = AbortHandle::new_pair();
    let child_fut = Abortable::new(async move {
        let status = child.await;
        println!("Child exited with status: {}", status);
        Ok::<_, Aborted>(())
    }, abort_registration);

    // Create a future that aborts the child future after a delay
    let delay_fut = async {
        delay_for(Duration::from_secs(2)).await;
        abort_handle.abort();
        Ok(())
    };

    // Wait for both to complete or one future to error
    tokio::try_join!(child_fut, delay_fut);
}

async fn main() {
    loop {
        do_work().await;
        delay_for(Duration::for_secs(10)).await;
    }
}

Что я хочу:

Я хочу прервать Command / Child и убить процесс unix. Это работает.

Я также хочу, чтобы unix завершился процесс. В конце концов это произойдет, но не раньше, чем завершится еще одна итерация delay_for, произойдет еще одна итерация основного l oop и снова будет вызвана do_work ().

Вопрос:

Я знаю, что если мой try_join обнаруживает ошибку Aborted, то дочерний процесс был прерван и завершен. Могу ли я вручную принудительно запустить глобальную дочернюю очередь-сирот, чтобы дочерний процесс unix был получен в конце do_work ()?

Или мне следует принять поведение по умолчанию? Но я хотел бы знать, как обеспечить, чтобы после завершения do_work () завершился несуществующий процесс.

Дополнительная информация:

Я увидел кое-что странное. Я запустил отладочную сборку в lldb. Когда я добавляю точку останова для tokio / src / process / unix / reap.rs: 136 в impl Drop for Reaper fn drop (). Если я немедленно продолжу работу отладчика, я вижу, что неработающий процесс unix выполняется немедленно, до main () delay_for (Duration :: from_secs (10)). Когда я запускаю код вне отладчика, я вижу, что дочерний элемент defunt получен после main () delay_for.

Я использую проект по умолчанию с car go new. Я добавил зависимости для tokio 0.2.21, но никаких дополнительных настроек не делал. Я использую сборку автомобиля go, сборку отладки.

Спасибо за ваше время и идеи.

...