2

start-processまたは同様の関数を使用してサブプロセスを開始したいEmacs Lispでいくつかのコードを書いています。ただし、親の 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")
   ))

このコードは、1 つの 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 が送信するシグナルを簡単に見つけることができます (プロセスの 1 つにシグナルハンドラーを書くだけです)。SIGHUP だと思いますので、プロセスはユーザー (Emacs) への接続が失われたことを認識しています。

できることは、たとえば、そのシグナルのハンドラーを追加することにより、プロセスが停止しないように SIGHUP を処理するようにすることです。そのプロセスコードをまったく制御できない場合は、「nohup」でラップできます(これは@abo-aboが基本的に行っていることです。実装の詳細については、abo-aboの他の回答を参照してください)

于 2013-11-12T09:56:57.787 に答える