Quoth Dmitry Kurochkin on Jun 28 at 5:03 am: > > > The only way I know to > > > reliably kill a child process is to open a pipe to it and have it exit > > > on its own when it reads EOF. Unfortunately, I couldn't find a way to > > > do this with an emacs daemon (it appears daemon mode aggressively > > > cleans up things like pipes), but here's a different approach: > > > > > > coproc emacs --batch --eval "(while t (eval (read)))" > > > EMACSFD=${COPROC[1]} > > > trap "echo '(kill-emacs)' >&$EMACSFD" EXIT > > > > > > echo '(message "Hi")' >&$EMACSFD > > > # ... > > > > > > This is, basically, a poor man's emacs server, but the coprocess pipe > > > binds it tightly to the shell. If the shell exits for *any* reason, > > > the pipe will be closed by the kernel, emacs will read an EOF, and > > > exit. > > > > I like this idea. > > > > > The trap is there just to cleanly shut down in case of a normal > > > exit [1]. > > > > For normal exit we should just put this into test_done. Otherwise it is > > not a normal exit and we do not care about Emacs error message. No? > > > > > This also has the advantage that read-from-minibuffer still > > > works: > > > > > > echo '(message (read-from-minibuffer ""))' >&$EMACSFD > > > echo 'Test' >&$EMACSFD > > > > > > Thoughts? > > > > > > > I like it and I will implement it. Thanks for the idea. > > > > While implementing the idea, I stumbled upon a problem: we need to know > when Emacs finished what we echoed or failed with an error. At the > moment tests fail because they check for OUTPUT before Emacs creates it. > > We can tell Emacs to print some special marker and wait for it. But > there may be exceptions and errors which may make it difficult. I did > not found a good solution yet. Would love to hear your thoughts :) Oof, yes, of course. How about making the one-line poor man's emacs server slightly less poor? Use a FIFO to communicate completion. Something like, EMACSDONE=$TEST_DIRECTORY/emacsdone mkfifo $EMACSDONE coproc emacs --batch --eval '(while t (eval (read)) (write-region "\n" nil "'$EMACSDONE'" t 0))' EMACSFD=${COPROC[1]} test_emacs() { echo "$1" >&$EMACSFD read <$EMACSDONE } test_emacs '(sleep-for 2)' test_emacs '(message "Hi")' echo '(kill-emacs)' >&$EMACSFD