call-process / shell-commandにタイムアウトを適用しますか?


7

場合によっては、作業を外部プロセスに委任するときに、コマンドにタイムアウトを設定して、Emacsが無期限にハングアップするのを防ぐと便利です。
残念ながら、以下は機能しません。

(with-timeout (1 nil)
  (call-process "/usr/bin/bash" nil t nil "-c" "sleep 10"))

同じことがについても言えshell-commandます。

これらの同期プロセスにタイムアウトを設定する方法はありますか?
つまり、プロセスが特定の秒数以内に完了しない場合、プロセスが自動的に強制終了されるようにしたいです。それは可能ですか?


使用したことはありませんが、使用with-timeoutしたことがkill-processありdelete-processます。
弁護士、2015年

確かではありませんが、プロセスの出力を受け入れると役立つ場合があります。つまり、Emacsにイニシアチブをとり、いくつかのElispコードを実行するように指示します。おそらくプロセスが出力を生成するのを待っています。おそらく、それがタイムアウトになった場合にプロセスを強制終了するのにも良い時期です。
wvxvw 2015年

@wvxvw call-process上記は、現在のバッファーに出力を出力するように設定しています(別の出力バッファーを渡しても同じ効果が得られます)。そういう意味ですか
マラバルバ2015年

いや、ごめんなさい、私はいくつかのことを混乱させました。つまりgnu.org / software / emacs / manual / html_node / elisp / …ですが、これは非同期プロセスにのみ関連します。私が家にいるときは、call-processソースを調べますが、タイムアウト時にそれを強制終了する方法がないのではないかと疑い始めています。
wvxvw 2015年

実際、Github:github.com/emacs-mirror/emacs/blob/…で調べようとしましたが、いいえ、プロセスのタイムアウトの設定などを行うコードはありません。
wvxvw 2015年

回答:


4

一方でcall-process実行されている、Emacsはイベントを処理しますが、with-timeoutこれなしでは動作しません。

Emacsが何らかの種類の外部イベント(キーボード入力、サブプロセスからの入力、または特定の時間など)を待機するたびに、タイムアウトがチェックされます。プログラムが待機せずにループする場合、タイムアウトは検出されません。

with-timeout(準)同期プロセスでも使用できます。

実際には非同期プロセスを使用しますが、実行中は同期して待機します。Emacsは実行時にイベントを処理しますsit-for。これは0秒間実行できます。次に、timeout-forms引数を使用してwith-timeout、タイムアウトが発生したときにプロセスがまだ実行されている場合はプロセスを強制終了できます。

(with-current-buffer (get-buffer-create "*my-proc-buffer*")
  (let ((proc (start-process "myproc" (current-buffer) "bash" "-c" "sleep 4"))) ;; start an async process
    (with-timeout (2 (kill-process proc)) ;; on timeout, kill the process
      (while (process-live-p proc) ;; while process is running
        (sit-for .05)) ;; let emacs read events and run timmers (and check for timeout)
      (message "finished on time!!")))) ;; this will run only if there is no timeout

私はこれに関して小さな問題を抱えています。ループの終了後、プロセスの出力が出力バッファーにあるとは限りません。ループの(sit-for 0.2)後に別のwhile関数を呼び出すことで回避していますが、不安定な感じがします。出力がバッファに出力されたことを確認する方法はありますか?
マラバルバ2015年

それについてはよくわかりません。ただし、タイムアウトに達した場合、プロセスはいずれにせよ実行されないため、出力は関係ありません。タイムアウト後も出力が必要になるように何をしていますか?プロセスフィルターの使用に切り替え、プロセスを強制終了する可能性があります。何も関係なく、X秒後ではなく、出力なしでX秒しか経過していません。
Jordon Biondo

すみません、よくわかりませんでした。タイムアウトになったときの出力は気にしません。プロセスが正常に完了した後、出力がすぐに印刷されないことを言っています。
マラバルバ2015年

問題は(sit-for 0)、emacsがプロセスを実行させるのに時間がかかりすぎ、イベントをリッスンしてテキストをバッファに挿入するのに十分ではないと私は思う 私の(sit-for .05)ものを物事に変更すると、うまく機能し、すべてのテキストが私のバッファに入ります。プロセスが短い場合でも、0.05秒は問題のオーバーヘッドではありません。
Jordon Biondo

この状況でのオーバーヘッドの心配はあまりありません。プロセスは5〜8回呼び出され、全体がすでに少なくとも数秒かかる対話型操作であるため、あと1秒でも大きな違いはありません。少し心配なのは、安定性(sit-for 0.2)です。ローカルテストに合格する必要があり、変更をプッシュしても、トラビステストが失敗したためです。
マラバルバ2015年

4

これは、シェルコマンドにGNUタイムアウト呼び出しを追加するだけで実現できます。これにより、Emacsの動作に関する詳細を知る必要がなくなります。たとえば、次のように実行します。

$ timeout 5 sleep 10

10秒ではなく5秒で戻ります(タイムアウトにより、Ctrl-Cが効果的に押されます)。


おかげで、他のオプションで安定性を実現できない場合は、このオプションを選択する必要があるかもしれません。ただし、別のユーティリティに依存しないようにしたいので、Windowsでも機能します。
マラバルバ2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.