【发布时间】:2013-11-12 23:55:48
【问题描述】:
我正在 Emacs Lisp 中编写一些代码,我想在其中使用 start-process 或类似函数启动子进程。但是,当父 emacs 进程退出时,我不希望子进程退出。但是,似乎退出父 emacs 进程也总是会杀死所有子进程。以下代码 sn -p 演示了这一点:
(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 行。
那么有没有类似的方法来启动一个子进程,这样子进程就不会在它的父进程退出时被杀死?
【问题讨论】:
-
ASYNC_LOG 中的哪一行表示意外行为?
SPAWNING: Mon Nov 11 12:53:25 UTC 2013;STARTED: Mon Nov 11 12:53:25 UTC 2013;SPAWNED: Mon Nov 11 12:53:25 UTC 2013;FINISHED WAITING: Mon Nov 11 12:53:27 UTC 2013;FINISHED: Mon Nov 11 12:53:30 UTC 2013? -
如果子进程的睡眠时间比父进程长,则永远不会出现FINISHED行,表示父进程退出时子进程被杀死。
-
我倒过来让父进程休眠2秒,子进程休眠5秒,得到的就是这个:
SPAWNING: Mon Nov 11 13:28:36 UTC 2013;STARTED: Mon Nov 11 13:28:36 UTC 2013;SPAWNED: Mon Nov 11 13:28:36 UTC 2013;FINISHED: Mon Nov 11 13:28:38 UTC 2013;FINISHED WAITING: Mon Nov 11 13:28:41 UTC 2013。我没有使用(require 'async),而是在不使用lambda ()的情况下将async-sandbox转换为(interactive)函数。我正在使用带有 Emacs Trunk 的 OSX Snow Leopard 10.6.8。 -
我的示例已经让父进程休眠 2 秒,子进程休眠 5 秒。从您评论中的时间戳来看,您似乎做了相反的事情。无论如何,如果没有
async-sandbox调用,该示例将无法运行,因为关键是要让父进程(由async-sandbox启动)在子进程(由start-process启动)之前退出。让它工作的另一种方法是在emacs -batch中运行它,因为无论如何这都是 async 所做的。 -
感谢您帮助我更好地理解问题。我已经安装了 github.com/jwiegley/emacs-async 并且可以确认与您的问题中描述的相同的行为(使用 OSX 10.6.8 和相当新版本的 Emacs Trunk)。但是,我还没有解决方案——抱歉。
标签: asynchronous emacs elisp multiprocessing parent-child