summaryrefslogtreecommitdiff
path: root/test/src/process-tests.el
diff options
context:
space:
mode:
Diffstat (limited to 'test/src/process-tests.el')
-rw-r--r--test/src/process-tests.el442
1 files changed, 414 insertions, 28 deletions
diff --git a/test/src/process-tests.el b/test/src/process-tests.el
index e15ad47f968..cddf955853e 100644
--- a/test/src/process-tests.el
+++ b/test/src/process-tests.el
@@ -1,6 +1,6 @@
;;; process-tests.el --- Testing the process facilities -*- lexical-binding: t -*-
-;; Copyright (C) 2013-2020 Free Software Foundation, Inc.
+;; Copyright (C) 2013-2021 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
@@ -23,8 +23,11 @@
;;; Code:
+(require 'cl-lib)
(require 'ert)
(require 'puny)
+(require 'rx)
+(require 'subr-x)
;; Timeout in seconds; the test fails if the timeout is reached.
(defvar process-test-sentinel-wait-timeout 2.0)
@@ -47,13 +50,15 @@
(ert-deftest process-test-sentinel-accept-process-output ()
(skip-unless (executable-find "bash"))
+ (with-timeout (60 (ert-fail "Test timed out"))
(should (process-test-sentinel-wait-function-working-p
- #'accept-process-output)))
+ #'accept-process-output))))
(ert-deftest process-test-sentinel-sit-for ()
(skip-unless (executable-find "bash"))
+ (with-timeout (60 (ert-fail "Test timed out"))
(should
- (process-test-sentinel-wait-function-working-p (lambda () (sit-for 0.01 t)))))
+ (process-test-sentinel-wait-function-working-p (lambda () (sit-for 0.01 t))))))
(when (eq system-type 'windows-nt)
(ert-deftest process-test-quoted-batfile ()
@@ -79,6 +84,7 @@
(ert-deftest process-test-stderr-buffer ()
(skip-unless (executable-find "bash"))
+ (with-timeout (60 (ert-fail "Test timed out"))
(let* ((stdout-buffer (generate-new-buffer "*stdout*"))
(stderr-buffer (generate-new-buffer "*stderr*"))
(proc (make-process :name "test"
@@ -103,10 +109,11 @@
(looking-at "hello stdout!")))
(should (with-current-buffer stderr-buffer
(goto-char (point-min))
- (looking-at "hello stderr!")))))
+ (looking-at "hello stderr!"))))))
(ert-deftest process-test-stderr-filter ()
(skip-unless (executable-find "bash"))
+ (with-timeout (60 (ert-fail "Test timed out"))
(let* ((sentinel-called nil)
(stderr-sentinel-called nil)
(stdout-output nil)
@@ -145,10 +152,11 @@
(should (equal 1 (with-current-buffer stderr-buffer
(point-max))))
(should (equal "hello stderr!\n"
- (mapconcat #'identity (nreverse stderr-output) "")))))
+ (mapconcat #'identity (nreverse stderr-output) ""))))))
(ert-deftest set-process-filter-t ()
"Test setting process filter to t and back." ;; Bug#36591
+ (with-timeout (60 (ert-fail "Test timed out"))
(with-temp-buffer
(let* ((print-level nil)
(print-length nil)
@@ -180,11 +188,12 @@
(line-beginning-position) (point-max))
"2> "))
(accept-process-output proc)) ; Read "Two".
- (should (equal (buffer-string) "0> one\n1> two\n2> ")))))
+ (should (equal (buffer-string) "0> one\n1> two\n2> "))))))
(ert-deftest start-process-should-not-modify-arguments ()
"`start-process' must not modify its arguments in-place."
;; See bug#21831.
+ (with-timeout (60 (ert-fail "Test timed out"))
(let* ((path (pcase system-type
((or 'windows-nt 'ms-dos)
;; Make sure the file name uses forward slashes.
@@ -198,11 +207,12 @@
(should (process-live-p (condition-case nil
(start-process "" nil path)
(error nil))))
- (should (equal path samepath))))
+ (should (equal path samepath)))))
(ert-deftest make-process/noquery-stderr ()
"Checks that Bug#30031 is fixed."
(skip-unless (executable-find "sleep"))
+ (with-timeout (60 (ert-fail "Test timed out"))
(with-temp-buffer
(let* ((previous-processes (process-list))
(process (make-process :name "sleep"
@@ -217,7 +227,7 @@
(should new-processes)
(dolist (process new-processes)
(should-not (process-query-on-exit-flag process))))
- (kill-process process)))))
+ (kill-process process))))))
;; Return t if OUTPUT could have been generated by merging the INPUTS somehow.
(defun process-tests--mixable (output &rest inputs)
@@ -233,6 +243,7 @@
(ert-deftest make-process/mix-stderr ()
"Check that `make-process' mixes the output streams if STDERR is nil."
(skip-unless (executable-find "bash"))
+ (with-timeout (60 (ert-fail "Test timed out"))
;; Frequent random (?) failures on hydra.nixos.org, with no process output.
;; Maybe this test should be tagged unstable? See bug#31214.
(skip-unless (not (getenv "EMACS_HYDRA_CI")))
@@ -251,11 +262,12 @@
(should (eq (process-exit-status process) 0))
(should (process-tests--mixable (string-to-list (buffer-string))
(string-to-list "stdout\n")
- (string-to-list "stderr\n"))))))
+ (string-to-list "stderr\n")))))))
(ert-deftest make-process-w32-debug-spawn-error ()
"Check that debugger runs on `make-process' failure (Bug#33016)."
(skip-unless (eq system-type 'windows-nt))
+ (with-timeout (60 (ert-fail "Test timed out"))
(let* ((debug-on-error t)
(have-called-debugger nil)
(debugger (lambda (&rest _)
@@ -271,11 +283,12 @@
;; code.
(make-process :name "test" :command '("c:/No-Such-Command"))
(error :got-error))))
- (should have-called-debugger)))
+ (should have-called-debugger))))
(ert-deftest make-process/file-handler/found ()
- "Check that the ‘:file-handler’ argument of ‘make-process’
+ "Check that the `:file-handler’ argument of `make-process’
works as expected if a file name handler is found."
+ (with-timeout (60 (ert-fail "Test timed out"))
(let ((file-handler-calls 0))
(cl-flet ((file-handler
(&rest args)
@@ -292,27 +305,29 @@ works as expected if a file name handler is found."
:command '("/some/binary")
:file-handler t)
'fake-process))
- (should (= file-handler-calls 1))))))
+ (should (= file-handler-calls 1)))))))
(ert-deftest make-process/file-handler/not-found ()
- "Check that the ‘:file-handler’ argument of ‘make-process’
+ "Check that the `:file-handler’ argument of `make-process’
works as expected if no file name handler is found."
+ (with-timeout (60 (ert-fail "Test timed out"))
(let ((file-name-handler-alist ())
(default-directory invocation-directory)
(program (expand-file-name invocation-name invocation-directory)))
(should (processp (make-process :name "name"
:command (list program "--version")
- :file-handler t)))))
+ :file-handler t))))))
(ert-deftest make-process/file-handler/disable ()
- "Check ‘make-process’ works as expected if it shouldn’t use the
+ "Check `make-process’ works as expected if it shouldn’t use the
file name handler."
+ (with-timeout (60 (ert-fail "Test timed out"))
(let ((file-name-handler-alist (list (cons (rx bos "test-handler:")
#'process-tests--file-handler)))
(default-directory "test-handler:/dir/")
(program (expand-file-name invocation-name invocation-directory)))
(should (processp (make-process :name "name"
- :command (list program "--version"))))))
+ :command (list program "--version")))))))
(defun process-tests--file-handler (operation &rest _args)
(cl-ecase operation
@@ -325,48 +340,419 @@ file name handler."
(ert-deftest make-process/stop ()
"Check that `make-process' doesn't accept a `:stop' key.
See Bug#30460."
+ (with-timeout (60 (ert-fail "Test timed out"))
(should-error
(make-process :name "test"
:command (list (expand-file-name invocation-name
invocation-directory))
- :stop t)))
+ :stop t))))
;; All the following tests require working DNS, which appears not to
;; be the case for hydra.nixos.org, so disable them there for now.
(ert-deftest lookup-family-specification ()
- "network-lookup-address-info should only accept valid family symbols."
+ "`network-lookup-address-info' should only accept valid family symbols."
(skip-unless (not (getenv "EMACS_HYDRA_CI")))
+ (with-timeout (60 (ert-fail "Test timed out"))
(should-error (network-lookup-address-info "google.com" 'both))
(should (network-lookup-address-info "google.com" 'ipv4))
(when (featurep 'make-network-process '(:family ipv6))
- (should (network-lookup-address-info "google.com" 'ipv6))))
+ (should (network-lookup-address-info "google.com" 'ipv6)))))
(ert-deftest lookup-unicode-domains ()
- "Unicode domains should fail"
+ "Unicode domains should fail."
(skip-unless (not (getenv "EMACS_HYDRA_CI")))
+ (with-timeout (60 (ert-fail "Test timed out"))
(should-error (network-lookup-address-info "faß.de"))
- (should (network-lookup-address-info (puny-encode-domain "faß.de"))))
+ (should (network-lookup-address-info (puny-encode-domain "faß.de")))))
(ert-deftest unibyte-domain-name ()
- "Unibyte domain names should work"
+ "Unibyte domain names should work."
(skip-unless (not (getenv "EMACS_HYDRA_CI")))
- (should (network-lookup-address-info (string-to-unibyte "google.com"))))
+ (with-timeout (60 (ert-fail "Test timed out"))
+ (should (network-lookup-address-info (string-to-unibyte "google.com")))))
(ert-deftest lookup-google ()
- "Check that we can look up google IP addresses"
+ "Check that we can look up google IP addresses."
(skip-unless (not (getenv "EMACS_HYDRA_CI")))
+ (with-timeout (60 (ert-fail "Test timed out"))
(let ((addresses-both (network-lookup-address-info "google.com"))
(addresses-v4 (network-lookup-address-info "google.com" 'ipv4)))
(should addresses-both)
(should addresses-v4))
(when (featurep 'make-network-process '(:family ipv6))
- (should (network-lookup-address-info "google.com" 'ipv6))))
+ (should (network-lookup-address-info "google.com" 'ipv6)))))
(ert-deftest non-existent-lookup-failure ()
+ "Check that looking up non-existent domain returns nil."
(skip-unless (not (getenv "EMACS_HYDRA_CI")))
- "Check that looking up non-existent domain returns nil"
- (should (eq nil (network-lookup-address-info "emacs.invalid"))))
+ (with-timeout (60 (ert-fail "Test timed out"))
+ (should (eq nil (network-lookup-address-info "emacs.invalid")))))
+
+(defmacro process-tests--ignore-EMFILE (&rest body)
+ "Evaluate BODY, ignoring EMFILE errors."
+ (declare (indent 0) (debug t))
+ (let ((err (make-symbol "err"))
+ (message (make-symbol "message")))
+ `(let ((,message (process-tests--EMFILE-message)))
+ (condition-case ,err
+ ,(macroexp-progn body)
+ (file-error
+ ;; If we couldn't determine the EMFILE message, just ignore
+ ;; all `file-error' signals.
+ (and ,message
+ (not (string-equal (caddr ,err) ,message))
+ (signal (car ,err) (cdr ,err))))))))
+
+(defmacro process-tests--with-buffers (var &rest body)
+ "Bind VAR to nil and evaluate BODY.
+Afterwards, kill all buffers in the list VAR. BODY should add
+some buffer objects to VAR."
+ (declare (indent 1) (debug (symbolp body)))
+ (cl-check-type var symbol)
+ `(let ((,var nil))
+ (unwind-protect
+ ,(macroexp-progn body)
+ (mapc #'kill-buffer ,var))))
+
+(defmacro process-tests--with-processes (var &rest body)
+ "Bind VAR to nil and evaluate BODY.
+Afterwards, delete all processes in the list VAR. BODY should
+add some process objects to VAR."
+ (declare (indent 1) (debug (symbolp body)))
+ (cl-check-type var symbol)
+ `(let ((,var nil))
+ (unwind-protect
+ ,(macroexp-progn body)
+ (mapc #'delete-process ,var))))
+
+(defmacro process-tests--with-raised-rlimit (&rest body)
+ "Evaluate BODY using a higher limit for the number of open files.
+Attempt to set the resource limit for the number of open files
+temporarily to the highest possible value."
+ (declare (indent 0) (debug t))
+ (let ((prlimit (make-symbol "prlimit"))
+ (soft (make-symbol "soft"))
+ (hard (make-symbol "hard"))
+ (pid-arg (make-symbol "pid-arg")))
+ `(let ((,prlimit (executable-find "prlimit"))
+ (,pid-arg (format "--pid=%d" (emacs-pid)))
+ (,soft nil) (,hard nil))
+ (cl-flet ((set-limit
+ (value)
+ (cl-check-type value natnum)
+ (when ,prlimit
+ (call-process ,prlimit nil nil nil
+ ,pid-arg
+ (format "--nofile=%d:" value)))))
+ (when ,prlimit
+ (with-temp-buffer
+ (when (eql (call-process ,prlimit nil t nil
+ ,pid-arg "--nofile"
+ "--raw" "--noheadings"
+ "--output=SOFT,HARD")
+ 0)
+ (goto-char (point-min))
+ (when (looking-at (rx (group (+ digit)) (+ blank)
+ (group (+ digit)) ?\n))
+ (setq ,soft (string-to-number
+ (match-string-no-properties 1))
+ ,hard (string-to-number
+ (match-string-no-properties 2))))))
+ (and ,soft ,hard (< ,soft ,hard)
+ (set-limit ,hard)))
+ (unwind-protect
+ ,(macroexp-progn body)
+ (when ,soft (set-limit ,soft)))))))
+
+(defmacro process-tests--fd-setsize-test (&rest body)
+ "Run BODY as a test for FD_SETSIZE overflow.
+Try to generate pipe processes until we are close to the
+FD_SETSIZE limit. Within BODY, only a small number of file
+descriptors should still be available. Furthermore, raise the
+maximum number of open files in the Emacs process above
+FD_SETSIZE."
+ (declare (indent 0) (debug t))
+ (let ((process (make-symbol "process"))
+ (processes (make-symbol "processes"))
+ (buffer (make-symbol "buffer"))
+ (buffers (make-symbol "buffers"))
+ ;; FD_SETSIZE is typically 1024 on Unix-like systems. On
+ ;; MS-Windows we artificially limit FD_SETSIZE to 64, see the
+ ;; commentary in w32proc.c.
+ (fd-setsize (if (eq system-type 'windows-nt) 64 1024)))
+ `(process-tests--with-raised-rlimit
+ (process-tests--with-buffers ,buffers
+ (process-tests--with-processes ,processes
+ ;; First, allocate enough pipes to definitely exceed the
+ ;; FD_SETSIZE limit.
+ (cl-loop for i from 1 to ,(1+ fd-setsize)
+ for ,buffer = (generate-new-buffer
+ (format " *pipe %d*" i))
+ do (push ,buffer ,buffers)
+ for ,process = (process-tests--ignore-EMFILE
+ (make-pipe-process
+ :name (format "pipe %d" i)
+ ;; Prevent delete-process from
+ ;; trying to read from pipe
+ ;; processes that didn't exit
+ ;; yet, because no one is
+ ;; writing to those pipes, and
+ ;; the read will stall.
+ :stop (eq system-type 'windows-nt)
+ :buffer ,buffer
+ :coding 'no-conversion
+ :noquery t))
+ while ,process
+ do (push ,process ,processes))
+ (unless (cddr ,processes)
+ (ert-fail "Couldn't allocate enough pipes"))
+ ;; Delete two pipes to test more edge cases.
+ (delete-process (pop ,processes))
+ (delete-process (pop ,processes))
+ ,@body)))))
+
+(defmacro process-tests--with-temp-file (var &rest body)
+ "Bind VAR to the name of a new regular file and evaluate BODY.
+Afterwards, delete the file."
+ (declare (indent 1) (debug (symbolp body)))
+ (cl-check-type var symbol)
+ (let ((file (make-symbol "file")))
+ `(let ((,file (make-temp-file "emacs-test-")))
+ (unwind-protect
+ (let ((,var ,file))
+ ,@body)
+ (delete-file ,file)))))
+
+(defmacro process-tests--with-temp-directory (var &rest body)
+ "Bind VAR to the name of a new directory and evaluate BODY.
+Afterwards, delete the directory."
+ (declare (indent 1) (debug (symbolp body)))
+ (cl-check-type var symbol)
+ (let ((dir (make-symbol "dir")))
+ `(let ((,dir (make-temp-file "emacs-test-" :dir)))
+ (unwind-protect
+ (let ((,var ,dir))
+ ,@body)
+ (delete-directory ,dir :recursive)))))
+
+;; Tests for FD_SETSIZE overflow (Bug#24325). The following tests
+;; generate lots of process objects of the various kinds. Running the
+;; tests with assertions enabled should not result in any crashes due
+;; to file descriptor set overflow. These tests first generate lots
+;; of unused pipe processes to fill up the file descriptor space.
+;; Then, they create a few instances of the process type under test.
+
+(ert-deftest process-tests/fd-setsize-no-crash/make-process ()
+ "Check that Emacs doesn't crash when trying to use more than
+FD_SETSIZE file descriptors (Bug#24325)."
+ (with-timeout (60 (ert-fail "Test timed out"))
+ (let ((sleep (executable-find "sleep")))
+ (skip-unless sleep)
+ (dolist (conn-type '(pipe pty))
+ (ert-info ((format "Connection type `%s'" conn-type))
+ (process-tests--fd-setsize-test
+ (process-tests--with-processes processes
+ ;; Start processes until we exhaust the file descriptor
+ ;; set size. We assume that each process requires at
+ ;; least one file descriptor.
+ (dotimes (i 10)
+ (let ((process
+ ;; Failure to allocate more file descriptors
+ ;; should signal `file-error', but not crash.
+ ;; Since we don't know the exact limit, we
+ ;; ignore `file-error'.
+ (process-tests--ignore-EMFILE
+ (make-process :name (format "test %d" i)
+ :command (list sleep "5")
+ :connection-type conn-type
+ :coding 'no-conversion
+ :noquery t))))
+ (when process (push process processes))))
+ ;; We should have managed to start at least one process.
+ (should processes)
+ (dolist (process processes)
+ (while (accept-process-output process))
+ (should (eq (process-status process) 'exit))
+ ;; If there's an error between fork and exec, Emacs
+ ;; will use exit statuses between 125 and 127, see
+ ;; process.h. This can happen if the child process
+ ;; tries to set up terminal device but fails due to
+ ;; file number limits. We don't treat this as an
+ ;; error.
+ (should (memql (process-exit-status process)
+ '(0 125 126 127)))))))))))
+
+(ert-deftest process-tests/fd-setsize-no-crash/make-pipe-process ()
+ "Check that Emacs doesn't crash when trying to use more than
+FD_SETSIZE file descriptors (Bug#24325)."
+ (with-timeout (60 (ert-fail "Test timed out"))
+ (process-tests--fd-setsize-test
+ (process-tests--with-buffers buffers
+ (process-tests--with-processes processes
+ ;; Start processes until we exhaust the file descriptor set
+ ;; size. We assume that each process requires at least one
+ ;; file descriptor.
+ (dotimes (i 10)
+ (let ((buffer (generate-new-buffer (format " *%d*" i))))
+ (push buffer buffers)
+ (let ((process
+ ;; Failure to allocate more file descriptors
+ ;; should signal `file-error', but not crash.
+ ;; Since we don't know the exact limit, we ignore
+ ;; `file-error'.
+ (process-tests--ignore-EMFILE
+ (make-pipe-process :name (format "test %d" i)
+ :buffer buffer
+ :coding 'no-conversion
+ :noquery t))))
+ (when process (push process processes)))))
+ ;; We should have managed to start at least one process.
+ (should processes))))))
+
+(ert-deftest process-tests/fd-setsize-no-crash/make-network-process ()
+ "Check that Emacs doesn't crash when trying to use more than
+FD_SETSIZE file descriptors (Bug#24325)."
+ (skip-unless (featurep 'make-network-process '(:server t)))
+ (skip-unless (featurep 'make-network-process '(:family local)))
+ (with-timeout (60 (ert-fail "Test timed out"))
+ (process-tests--with-temp-directory directory
+ (process-tests--with-processes processes
+ (let* ((num-clients 10)
+ (socket-name (expand-file-name "socket" directory))
+ ;; Run a UNIX server to connect to.
+ (server (make-network-process :name "server"
+ :server num-clients
+ :buffer nil
+ :service socket-name
+ :family 'local
+ :coding 'no-conversion
+ :noquery t)))
+ (push server processes)
+ (process-tests--fd-setsize-test
+ ;; Start processes until we exhaust the file descriptor
+ ;; set size. We assume that each process requires at
+ ;; least one file descriptor.
+ (dotimes (i num-clients)
+ (let ((client
+ ;; Failure to allocate more file descriptors
+ ;; should signal `file-error', but not crash.
+ ;; Since we don't know the exact limit, we ignore
+ ;; `file-error'.
+ (process-tests--ignore-EMFILE
+ (make-network-process
+ :name (format "client %d" i)
+ :service socket-name
+ :family 'local
+ :coding 'no-conversion
+ :noquery t))))
+ (when client (push client processes))))
+ ;; We should have managed to start at least one process.
+ (should processes)))))))
+
+(ert-deftest process-tests/fd-setsize-no-crash/make-serial-process ()
+ "Check that Emacs doesn't crash when trying to use more than
+FD_SETSIZE file descriptors (Bug#24325)."
+ (with-timeout (60 (ert-fail "Test timed out"))
+ (skip-unless (file-executable-p shell-file-name))
+ (skip-unless (executable-find "tty"))
+ (skip-unless (executable-find "sleep"))
+ ;; `process-tests--new-pty' probably only works with GNU Bash.
+ (skip-unless (string-equal
+ (file-name-nondirectory shell-file-name) "bash"))
+ (process-tests--with-processes processes
+ ;; In order to use `make-serial-process', we need to create some
+ ;; pseudoterminals. The easiest way to do that is to start a
+ ;; normal process using the `pty' connection type. We need to
+ ;; ensure that the terminal stays around while we connect to it.
+ ;; Create the host processes before the dummy pipes so we have a
+ ;; high chance of succeeding here.
+ (let ((tty-names ()))
+ (dotimes (_ 10)
+ (cl-destructuring-bind
+ (host tty-name) (process-tests--new-pty)
+ (should (processp host))
+ (push host processes)
+ (should tty-name)
+ (should (file-exists-p tty-name))
+ (push tty-name tty-names)))
+ (process-tests--fd-setsize-test
+ (process-tests--with-processes processes
+ (process-tests--with-buffers buffers
+ (dolist (tty-name tty-names)
+ (let ((buffer (generate-new-buffer
+ (format " *%s*" tty-name))))
+ (push buffer buffers)
+ ;; Failure to allocate more file descriptors should
+ ;; signal `file-error', but not crash. Since we
+ ;; don't know the exact limit, we ignore
+ ;; `file-error'.
+ (let ((process (process-tests--ignore-EMFILE
+ (make-serial-process
+ :name (format "test %s" tty-name)
+ :port tty-name
+ :speed 9600
+ :buffer buffer
+ :coding 'no-conversion
+ :noquery t))))
+ (when process (push process processes))))))
+ ;; We should have managed to start at least one process.
+ (should processes)))))))
+
+(defvar process-tests--EMFILE-message :unknown
+ "Cached result of the function `process-tests--EMFILE-message'.")
+
+(defun process-tests--EMFILE-message ()
+ "Return the error message for the EMFILE POSIX error.
+Return nil if that can't be determined."
+ (when (eq process-tests--EMFILE-message :unknown)
+ (setq process-tests--EMFILE-message
+ (with-temp-buffer
+ (when (eql (ignore-error 'file-error
+ (call-process "errno" nil t nil "EMFILE"))
+ 0)
+ (goto-char (point-min))
+ (when (looking-at (rx "EMFILE" (+ blank) (+ digit)
+ (+ blank) (group (+ nonl))))
+ (match-string-no-properties 1))))))
+ process-tests--EMFILE-message)
+
+(defun process-tests--new-pty ()
+ "Allocate a new pseudoterminal.
+Return a list (PROCESS TTY-NAME)."
+ ;; The command below will typically only work with GNU Bash.
+ (should (string-equal (file-name-nondirectory shell-file-name)
+ "bash"))
+ (process-tests--with-temp-file temp-file
+ (should-not (file-remote-p temp-file))
+ (let* ((command (list shell-file-name shell-command-switch
+ (format "tty > %s && sleep 60"
+ (shell-quote-argument
+ (file-name-unquote temp-file)))))
+ (process (make-process :name "tty host"
+ :command command
+ :buffer nil
+ :coding 'utf-8-unix
+ :connection-type 'pty
+ :noquery t))
+ (tty-name nil)
+ (coding-system-for-read 'utf-8-unix)
+ (coding-system-for-write 'utf-8-unix))
+ ;; Wait until TTY name has arrived.
+ (with-timeout (2 (message "Timed out waiting for TTY name"))
+ (while (and (process-live-p process) (not tty-name))
+ (sleep-for 0.1)
+ (when-let ((attributes (file-attributes temp-file)))
+ (when (cl-plusp (file-attribute-size attributes))
+ (with-temp-buffer
+ (insert-file-contents temp-file)
+ (goto-char (point-max))
+ ;; `tty' has printed a trailing newline.
+ (skip-chars-backward "\n")
+ (unless (bobp)
+ (setq tty-name (buffer-substring-no-properties
+ (point-min) (point)))))))))
+ (list process tty-name))))
(provide 'process-tests)
-;; process-tests.el ends here.
+;;; process-tests.el ends here