Канал пуст после передачи своего файлового дескриптора подпроцессу, который записал в него - PullRequest
2 голосов
/ 31 мая 2019

Следующие коды Python создают канал с os.pipe() и передают свои файловые дескрипторы подпроцессу через pass_fds из subprocess.Popen(). stdout, stderr, а код возврата ведет себя как ожидалось. Однако попытка прочитать канал с os.fdopen() после завершения подпроцесса ничего не даст; программа не завершается, потому что read() постоянно ожидает, что что-то будет записано в канал.

import subprocess as sp
import os

r, w = os.pipe()
p = sp.Popen(
    ["fd_test", str(w)],
    text=True,
    stdout=sp.PIPE,
    stderr=sp.PIPE,
    pass_fds=(r, w)
)
stdout, stderr = p.communicate()
print(stdout)
print(stderr)
print(p.returncode)

with os.fdopen(r, "r") as msg:
    print(msg.read())

Подпроцесс, fd_test, представляет собой короткую программу, написанную мной на C ++, которая пишет "Hello, world!" к данному дескриптору файла:

#include <cstdio>
#include <string>
#include <unistd.h>

int main(int argc, char* argv[]) {
    if (argc < 2)
        return 1;

    int fd = std::stoi(std::string(argv[1]));
    std::string msg = "Hello, world!\n";

    if (write(fd, msg.c_str(), msg.size()) == -1) {
        std::fprintf(stderr, "Failed to write to '%d'\n", fd);
        return 1;
    }

    /*char* buf[512] = {0};
    if (read(fd - 1, buf, 512) == -1 {
        std::fprintf(stderr, "Failed to read from %d'\n", fd - 1);
        return 1;
    }
    std::printf("%s", buf);*/

    std::printf("Wrote message to %d\n", fd);
    std::fprintf(stderr, "No errors, hurray!\n");
}

Программа не сообщает об ошибках записи в дескриптор файла. Фактически, закомментированный код может успешно читать только что написанное, а родительский процесс Python - нет.

Как я могу это исправить? Единственное, о чем я мог подумать, это os.set_inheritable(), но это не помогло.

...