2

我正在 Emacs Lisp 中编写一些代码,我想在其中使用start-process或类似函数启动子进程。但是,当父 emacs 进程退出时,我不希望子进程退出。但是,似乎退出父 emacs 进程也总是会杀死所有子进程。以下代码片段演示了这一点:

(require 'async)
(async-sandbox
 (lambda () 
   (require 'package)
   (package-initialize)
   (require 'async)
   (shell-command "{ echo -n 'SPAWNING: '; date; } > ~/temp/ASYNC_LOG")
   (start-process-shell-command "subproc" nil
    "{ echo -n 'STARTED: '; date; } >> ~/temp/ASYNC_LOG;
     sleep 5;
     { echo -n 'FINISHED: '; date; } >> ~/temp/ASYNC_LOG;")
   (shell-command "{ echo -n 'SPAWNED: '; date; } >> ~/temp/ASYNC_LOG")
   (shell-command "sleep 2")
   (shell-command "{ echo -n 'FINISHED WAITING: '; date; } >> ~/temp/ASYNC_LOG")
   ))

此代码同步生成一个 emacs 进程(async-sandbox (lambda () ...),以便我们可以退出该进程以触发问题。然后该进程异步生成一个子进程(start-process-shell-command ...)。父进程休眠2秒,子进程休眠5秒,所以父进程会先退出。当我运行这段代码时,我从未在日志文件中看到“FINISHED”行,这表明子进程在 2 秒后被杀死。如果我将父级更改为等待 7 秒,那么我会在输出中看到 FINISHED 行。

那么有没有类似的方法来启动一个子进程,这样它就不会在它的父进程退出时被杀死?

4

2 回答 2

2

以下是我从 dired 开始的方法:

(require 'dired-aux)
(setq dired-guess-shell-alist-user
      '(("\\.pdf\\'" "evince")
        ("\\.eps\\'" "evince")
        ("\\.jpe?g\\'" "eog")
        ("\\.png\\'" "eog")
        ("\\.gif\\'" "eog")
        ("\\.tex\\'" "pdflatex" "latex")
        ("\\.\\(?:mp4\\|mkv\\|avi\\|flv\\)\\'" "vlc")))
(defvar dired-filelist-cmd
  '(("vlc" "-L")))
(defun dired-start-process (cmd &optional file-list)
  (interactive
   (let ((files (dired-get-marked-files t current-prefix-arg)))
     (list
      (dired-read-shell-command "& on %s: " current-prefix-arg files)
      files))) 
  (apply
   #'start-process
   (list cmd nil shell-file-name shell-command-switch
         (format "nohup 1>/dev/null 2>/dev/null %s \"%s\""
                 (if (> (length file-list) 1)
                     (format "%s %s"
                             cmd
                             (cadr (assoc cmd dired-filelist-cmd)))
                   cmd)
                 (mapconcat #'expand-file-name file-list "\" \"")))))
于 2013-11-11T19:16:41.093 回答
0

Emacs 在终止时所做的是向其衍生的进程发送一个信号(我假设它们是存在于 中的那些process-list)。这种行为在 Emacs C 代码中是硬编码的(你可以尝试破解进程列表来删除你想要比 Emacs 更长寿的进程,但我不确定这样做的副作用;可能它们会很丑)

您可以轻松找出 Emacs 发送的信号(只需为您的一个进程编写信号处理程序)。我猜它是 SIGHUP,所以进程知道与用户(Emacs)的连接已经丢失。

您可以做的是让您的进程以一种不会死亡的方式处理 SIGHUP,例如为该信号添加一个处理程序。如果您对该流程代码的控制为零,则可以用“nohup”包装它(这就是@abo-abo 基本上正在做的事情;有关实现细节,请参见 abo-abo 其他答案)

于 2013-11-12T09:56:57.787 回答