Skip to content

Do not call alert subprocesses synchronously #116

@LemonBreezes

Description

@LemonBreezes

This can cause Emacs to lock up if Emacs is being used as the notification daemon (ie EDNC). I use this advice to get around this:

(defun cae-notifications-call-process-advice (orig-fun program &optional infile destination display &rest args)
  "Advice function to make `call-process` run asynchronously using `start-process`."
  ;; Generate a unique process name
  (let* ((process-name (generate-new-buffer-name (concat "async-" (file-name-nondirectory program))))
         ;; Determine the buffer based on DESTINATION
         (buffer (cond
                  ((eq destination t) (current-buffer))
                  ((bufferp destination) destination)
                  ((stringp destination) (get-buffer-create destination))
                  ((and (listp destination)
                        (eq (car destination) :file))
                   ;; For DESTINATION of the form (:file FILE), create a temporary buffer
                   (generate-new-buffer (concat "*" process-name "*")))
                  (t nil))) ;; For nil or 0, output is discarded
         ;; Use a pipe for the process communication
         (process-connection-type nil)
         ;; Start the process asynchronously
         (proc (apply 'start-process process-name buffer program args)))
    ;; If INFILE is specified, send its contents to the process
    (when infile
      (with-temp-buffer
        (insert-file-contents infile)
        (process-send-region proc (point-min) (point-max)))
      (process-send-eof proc)) ;; Signal that we've finished sending input
    ;; Handle DESTINATION being (:file FILE)
    (when (and (listp destination)
               (eq (car destination) :file))
      (let ((file (cadr destination)))
        ;; Set up a sentinel to write output to FILE when the process exits
        (set-process-sentinel
         proc
         (lambda (proc event)
           (when (eq (process-status proc) 'exit)
             (with-current-buffer (process-buffer proc)
               (write-region (point-min) (point-max) file nil 'quiet))
             (kill-buffer (process-buffer proc)))))))
    ;; If DISPLAY is non-nil and a buffer is associated, display the buffer
    (when (and display buffer)
      (display-buffer buffer))
    ;; Since the process is asynchronous, we return nil
    nil))

;;;###autoload
(defun cae-notifications-wrap-async-call-process-a (oldfun &rest args)
  (advice-add #'call-process :around #'cae-ednc-call-process-advice)
  (unwind-protect (apply oldfun args)
    (advice-remove #'call-process #'cae-ednc-call-process-advice)))

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions