Как сразу выйти из команды exe c через отмену контекста? - PullRequest
0 голосов
/ 03 мая 2020

Я передаю вывод команды клиенту с этим кодом. Команда построена с отменой контекста. Клиент отправляет запрос «отмена» на сервер, который уведомляет cancelCh клиента, который запускает cancel().

Проблема, с которой я сталкиваюсь, заключается в том, что когда команда отменяется, остальные выходные команды выводятся в поток. клиенту, как будто команда не была отменена. После того, как команда выполнена, exit status 1 получено; который показывает, что команда действительно была отменена.

Если я переместлю канал done в блок после cmd.Wait() вместо того, чтобы раньше, я получу поведение, которое ожидаю. Клиент сразу получает exit status 1 и данные больше не отправляются. Но это, кажется, вызывает проблему гонки данных: https://github.com/golang/go/issues/19685. Эта проблема устарела, но я думаю, что она актуальна.

Как правильно передавать потоковые данные клиенту в режиме реального времени, а также сразу же завершать работу через отмену контекста?

go func() {
    defer func() {
       cancel()
    }()
    <-client.cancelCh
}()

output := make(chan []byte)
go execute(cmd, output)

for data := range output {
    fmt.Fprintf(w, "data: %s\n\n", data)
    flusher.Flush()             
}
func execute(cmd *exec.Cmd, output chan []byte) {
    defer close(output)

    cmdReader, err := cmd.StdoutPipe()
    if err != nil {
        output <- []byte(fmt.Sprintf("Error getting stdout pipe: %v", err))
        return
    }
    cmd.Stderr = cmd.Stdout

    scanner := bufio.NewScanner(cmdReader)
    done := make(chan struct{})

    go func() {
        for scanner.Scan() {
            output <- scanner.Bytes()
        }
        done <- struct{}{}
    }()

    err = cmd.Start()
    if err != nil {
        output <- []byte(fmt.Sprintf("Error executing: %v", err))
        return
    }

    <-done

    err = cmd.Wait()
    if err != nil {
        output <- []byte(err.Error())
    }

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