Почему канал к другому процессу должен быть закрыт, а set_close_on_exec действительно закрыт? - PullRequest
0 голосов
/ 30 сентября 2018

Итак, я пытался использовать OCaml для связи с процессом Python.Я хотел передать программу Python в stdin интерпретатора Python, а затем прочитать вывод программы Python обратно в процесс OCaml.

Я смог решить ее следующим образом:

let py_program = {|
import time

while True:
    print('hi from Python', flush=True)
    time.sleep(0.25)
|}

let exec_py_program () =
  let cmd = "", [|"python3"; "-"|] in
  let pipe_out_fd, pipe_out_fd_unix = Lwt_unix.pipe_out () in

  (* Close the 1st time *)
  let () = Lwt_unix.set_close_on_exec pipe_out_fd_unix in

  let redir = `FD_move pipe_out_fd in

  let py_stream = Lwt_process.pread_lines ~stdin:redir cmd in

  let%lwt n = Lwt_unix.write_string pipe_out_fd_unix py_program 0 (String.length py_program) in
  if n < String.length py_program then failwith "Failed to write python to pipe" else

    let rec read_back () =
      match%lwt Lwt_stream.get py_stream with
      | Some str ->
        let%lwt () = Lwt_io.printl @@ "Got: " ^ str in
        read_back ()
      | None -> Lwt.return ()
    in

    (* Close the 2nd time *)
    let%lwt () = Lwt_unix.close pipe_out_fd_unix in

    read_back ()

Я использую "set_close_on_exec", чтобы закрыть файловый дескриптор, соответствующий каналу, отображаемому в stdin процесса Python возле комментария "Закрыть первый раз", и снова закрыть канал после повторной отправки через программу Python ("Закрыть второй раз"),«set_close_on_exec» предположительно закрывает дескриптор файла «когда процесс вызывает exec для другого процесса».

Если я пропускаю любую из этих строк, процесс Python бесконечно продолжает чтение со своего стандартного ввода и никогда не начинает выполняться, поэтому »привет от Python "никогда не получен.Итак, мой вопрос, почему они оба необходимы?Это было в основном предположение с моей стороны.

1 Ответ

0 голосов
/ 10 октября 2018

Запуск программы в операционной системе POSIX (например, Linux) выполняется в два этапа.Во-первых, процесс запуска программы разветвляется, что создает копию запущенного процесса.Затем новый процесс заменяется новой программой с использованием вызова exec.Когда процесс разветвляется, оба результирующих процесса наследуют все открытые дескрипторы файлов.Следовательно, чтобы фактически закрыть файловый дескриптор, он должен быть закрыт в обоих процессах.

Установка флага close-on-exec заставляет процесс закрыть соответствующий файловый дескриптор, как только exec называется.Следовательно, когда вы устанавливаете этот флаг, только старый процесс имеет дескриптор открытого файла после запуска программы.

См. Также этот вопрос .

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