`start-process`启动的子流程能否比父emacs流程更长?

时间:2013-11-11 19:07:23

标签: asynchronous emacs elisp multiprocessing parent-child

我正在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行。

那么有没有类似的方法来启动子进程,以便在父进程退出时不会被终止?

2 个答案:

答案 0 :(得分:1)

以下是我从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 "\" \"")))))

答案 1 :(得分:0)

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

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

您可以做的是通过为该信号添加处理程序,使您的进程以不会死的方式处理SIGHUP。如果您对该过程代码没有控制权,您可以用“nohup”包装它(这是@ abo-abo基本上正在做的事情;请参阅abo-abo其他答案以获取实现细节)