jwiegley/emacs-async

async-start generates a "*emacs*:err" buffer

xiliuya opened this issue · 11 comments

I tested under emacs - Q
When I run the following code in emacs 29 an error buffer is generated.

(async-start
       ;; What to do in the child process
       (lambda ()
         (message "This is a test")
         (sleep-for 3)
         222)

       ;; What to do when it finishes
       (lambda (result)
         (message "Async process done, result should be 222: %s"
                  result)))

The buffer contents are as follows:

This is a test

Process emacs stderr finished

Is this normal?

How can I avoid generating such a buffer?

The version I use is as follows:
OS: Archlinux
version: GNU Emacs 29.0.60 (build 25, x86_64-pc-linux-gnu, GTK+ Version 3.24.37, cairo version 1.17.8) of 2023-03-19)
async version: async-20230314.1202

Is this normal?
I guess yes, see PR #167 , perhaps @Fuco1 can give you more detailed explanations.
How can I avoid generating such a buffer?
Is this really annoying?

Fuco1 commented

Hi @xiliuya . This is normal because processes have two output streams: stdout and stderr.

When you run Emacs as a batch process, the message output actually goes to standard error and princ (or prin1) goes to standard output. It is important not to mix the two because emacs-async uses the standard output to communicate between parent and child processes (when using subprocess Emacs to run Elisp code). The error buffer should automatically disappear after the subprocess finishes, is that not the case? If so, we should take care to get rid of it except maybe when async-debug is on.

The presence of this buffer does not mean there has been an error. This is just the way Emacs handles the output streams. See Elisp manual: https://www.gnu.org/software/emacs/manual/html_node/elisp/Asynchronous-Processes.html#index-make_002dprocess specifically

:stderr stderr
Associate stderr with the standard error of the process. A non-nil value should be either a buffer or a pipe process created with make-pipe-process, described below. If stderr is nil, standard error is mixed with standard output, and both are sent to buffer or filter.

If stderr is a buffer, Emacs will create a pipe process, the standard error process. This process will have the default filter (see Process Filter Functions), sentinel (see Sentinels: Detecting Process Status Changes), and coding systems (see Default Coding Systems). On the other hand, it will use query-flag as its query-on-exit flag (see Querying Before Exit). It will be associated with the stderr buffer (see Process Buffers) and send its output (which is the standard error of the main process) there. To get the process object for the standard error process, pass the stderr buffer to get-buffer-process.

If stderr is a pipe process, Emacs will use it as standard error process for the new process.

The error buffer should automatically disappear after the subprocess finishes, is that not the case?

@Fuco1 NoYes.
The current situation is this buffer will always exist after the process ends.
The following code only killed *emacs* and did not kill *emacs*:error

(defun async-handle-result (func result buf)
  (if (null func)
      (progn
        (set (make-local-variable 'async-callback-value) result)
        (set (make-local-variable 'async-callback-value-set) t))
    (unwind-protect
        (if (and (listp result)
                 (eq 'async-signal (nth 0 result)))
            (signal (car (nth 1 result))
                    (cdr (nth 1 result)))
          (funcall func result))
      (unless async-debug
        (kill-buffer buf)))))

Is this normal?
I guess yes, see PR #167 , perhaps @Fuco1 can give you more detailed explanations.
How can I avoid generating such a buffer?
Is this really annoying?

@thierryvolpiatto Yes, when I execute such code 10 times, there will be 10 such buffers.
As shown in the following figure:
2023-03-21-095315

I modified async.el to have only one *emacs*: error buffer. This solved my problem.
Thank you for your help!
@Fuco1 @thierryvolpiatto

404c404
<          (buf-err (generate-new-buffer (concat "*" name "*:err")))
---
>          (buf-err (get-buffer-create (concat "*" name "*:err")))

Another way is to detect async-debug:

404c404,405
<          (buf-err (generate-new-buffer (concat "*" name "*:err")))
---
>          (buf-err (when async-debug
>                     (generate-new-buffer (concat "*" name "*:err"))))
Fuco1 commented

@thierryvolpiatto This is not good, the buffer must always exist to separate the output streams. Rather we should make sure to kill it afterwards. There seems to be similar code to kill the regular process buffer. I guess emacs keeps them around for you to "inspect" the command output.

Confirming as fixed for 28.1. Thanks!

Fuco1 commented

It's not fixed, it breaks other features. By the way, the buffers automatically close for me on Emacs 28.2. Do you have some special setting to keep them around? Even on emacs -Q on 28 they disappear automatically. Ok, they do not, I had an issue in my test script.

I will add an exit sentinel on the error buffer.