41.9.4 Прием вывода от процессов

Вывод из асинхронных подпроцессов обычно поступает только тогда, когда Emacs ожидает какого-либо внешнего события, такого как истечение времени или ввод с терминала. Иногда в программе на Lisp полезно явно разрешить поступление вывода в определенной точке или даже дождаться поступления вывода от процесса.

Функция: accept-process-output &optional process seconds millisec just-this-one

Эта функция позволяет Emacs считывать ожидающий вывод от процессов. Вывод передается в их функции фильтрации. Если process не равен nil, то эта функция не возвращает значение, пока не будет получен какой-либо вывод от process или пока process не закроет соединение.

Аргументы seconds и millisec позволяют указать периоды таймаута. Первый указывает период, измеренный в секундах, а второй — в миллисекундах. Эти два временных периода суммируются, и accept-process-output возвращает значение после этого времени, даже если нет вывода из подпроцесса.

Аргумент millisec устарел (и не следует использовать), потому что seconds может быть числом с плавающей точкой для указания ожидания дробного числа секунд. Если seconds равен 0, функция принимает любой ожидающий вывод, но не ждет.

Если process — это процесс, и аргумент just-this-one не равен nil, обрабатывается только вывод из этого процесса, приостанавливая вывод из других процессов до тех пор, пока не будет получен вывод из этого процесса или не истечет таймаут. Если just-this-one является целым числом, также ингибируются работающие таймеры. Эта функция, как правило, не рекомендуется, но может быть необходима для определенных приложений, таких как синтез речи.

Функция accept-process-output возвращает не-nil, если она получила вывод от process, или от любого процесса, если process равен nil; это может произойти даже после завершения процесса, если соответствующее соединение содержит буферизованные данные. Функция возвращает nil, если истек таймаут или соединение было закрыто до поступления вывода.

Если соединение от процесса содержит буферизованные данные, accept-process-output может вернуть не-nil, даже после завершения процесса. Поэтому, хотя следующий цикл:

;; Этот цикл содержит ошибку.
(while (process-live-p process)
  (accept-process-output process))

часто считывает весь вывод из process, он содержит состояние гонки и может пропустить некоторый вывод, если process-live-p возвращает nil, в то время как соединение все еще содержит данные. Лучше написать цикл так:

(while (accept-process-output process))

Если вы передали не-nil stderr в make-process, у него будет процесс стандартной ошибки. См. Создание асинхронного процесса. В этом случае ожидание вывода процесса от основного процесса не ждет вывода от процесса стандартной ошибки. Чтобы убедиться, что вы получили как весь стандартный вывод, так и всю стандартную ошибку от процесса, используйте следующий код:

(while (accept-process-output process))
(while (accept-process-output stderr-process))

Если вы передали буфер в аргумент stderr make-process, вам все равно нужно ждать процесса стандартной ошибки, как показано ниже:

(let* ((stdout (generate-new-buffer "stdout"))
       (stderr (generate-new-buffer "stderr"))
       (process (make-process :name "test"
                              :command '("my-program")
                              :buffer stdout
                              :stderr stderr))
       (stderr-process (get-buffer-process stderr)))
  (unless (and process stderr-process)
    (error "Process unexpectedly nil"))
  (while (accept-process-output process))
  (while (accept-process-output stderr-process)))

Только когда оба вызова accept-process-output возвращают nil, вы можете быть уверены, что процесс завершился, и Emacs прочитал весь его вывод.

Чтение ожидающей стандартной ошибки от процесса, работающего на удаленном хосте, таким образом невозможно.