Почему подпроцесс "сон 10" не завершается? - PullRequest
0 голосов
/ 29 мая 2020

Мне нужно проверить, завершается ли процесс, и все, что у меня есть, это его номер pid. Для этого я проверяю, существует ли псевдо-файл «/ proc / ».

Написав тест для этой функции, я заметил, что процесс не завершается должным образом.

Для теста я запускаю "sleep 10" как подпроцесс, который должен работать в течение 10 секунд. После запуска этого процесса я опрашиваю исчезновение псевдофайла «/ proc / ». Этот псевдофайл никогда не исчезает, и завершение подпроцесса не обнаруживается.

При тестировании кода golang игровая площадка воспроизводится проблема: https://play.golang.org/p/fb4CbXkIjh3.

Я проверил, что процесс создан, и что pid правильный. При проверке процесса видно, что он превращается в . Таким образом, он не удаляется.

Вопросы следующие:

  1. почему не завершается подпроцесс?
  2. как я могу изменить код заставить его прекратить?
package main

import (
    "fmt"
    "log"
    "os"
    "os/exec"
    "strconv"
    "time"
)

func main() {
    fmt.Println("Hello, playground")

    cmd := exec.Command("sleep", "10")
    if err := cmd.Start(); err != nil {
        log.Fatal("unexpected error:", err)
    }
    pidStr := strconv.Itoa(cmd.Process.Pid)
    log.Println("sleep pid:", pidStr)

    for {
        if _, err := os.Stat("/proc/" + pidStr); os.IsNotExist(err) {
            log.Println("detect termination of /proc/" + pidStr)
            return
        }
        log.Println("pgm /proc/" + pidStr + " is running")
        time.Sleep(3 * time.Second)
    }
}

1 Ответ

5 голосов
/ 29 мая 2020

На уровне ОС в любой POSIX-совместимой ОС (Unix, Linux, Darwin и др. c) процесс, который завершился, но еще не был собран его вышестоящим, находится в "несуществующем" состояние "или" зомб ie ". Он все еще существует, но его нельзя убить: он уже мертв. Он существует именно для того, чтобы его старший - процесс, который может вызывать системный вызов уровня ОС wait - может вызывать системный вызов уровня ОС wait и видеть , что процесс теперь мертв.

Как только его начальник дождался этого, процесс действительно удален: больше нет процесса-зомба ie, захватывающего этот идентификатор процесса. Если у вас файловая система /proc, это происходит тогда, когда процесс исчезает из /proc.

В Go вызов cmd.Wait() вызывает вызов wait уровня ОС, так что это способ сделать это. Если вы хотите получить результат этого cmd.Wait(), хороший способ сделать это - отправить его по каналу.

(Если вы хотите запустить очень долгий процесс и не ждать его , вы можете отклонить его, так что вы больше не будете его начальником. Подробности о том, как сделать это правильно, полны c мелочей, специфичных для ОС, таких как отмена контрольных ttys, установка сеансов с использованием procctl или prctl и т. д.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...