0

summary

Emacs processes currently (since version=23?) can be run from a "normal"/non-Emacs commandline in 1 of 3 modes:

  1. classic. (AFAICS this is my usage--please correct if there is a preferred term.) This was for decades the only way to run Emacs, and still (IIUC, ICBW) the only way one can run emacs --debug-init . I'll refer to such processes as classics.
  2. daemon aka server. An Emacs daemon process can be started either by
    • emacs --daemon : starts a new daemon process (only)
    • emacsclient --alternate-editor='' : starts a client process, and also a new daemon process if one was not already running
  3. client : started with emacsclient. Emacs client processes can be
    • GUI (in new window) if started with --create-frame
    • TUI (in same terminal) if started with --tty

From a commandline, one can normally easily discriminate clients from classics and daemons, since their process name=emacsclient by default. However the default process name for both classics and daemons is emacs :-( So how to discriminate--from a commandline, i.e., not from within Emacs--between classic and daemon processes?

Elisp daemonp allows one to query a running process regarding whether or not it is an Emacs daemon. This works cleanly from commandline if the process is a daemon, as illustrated below. But if the process is a classic, it fails if used as designed. So is there a clean, reliable way to discriminate between classic and daemon processes from a ("normal"/non-Emacs) commandline?

Note regarding potential answers: if your answer requires some interaction, please make it either

  1. (preferred) in the "same commandline." Not sure if that's the correct usage (please correct if not); what I mean is something like

    me@it: ~ $ your --code --here
    false
    
  2. (acceptable) in a TUI Emacs in the same shell as the commandline, like (e.g.) emacsclient --tty

details

testcase

Let's start with no emacs* processes:

me@it: ~ $ date ; emacs --version
Mon Oct  9 23:50:18 MST 2017
GNU Emacs 24.4.1
...

FWIW, I'm running this on an up-to-date Debian (currently version=8.9) Linux, hence the somewhat downlevel Emacs.

me@it: ~ $ date ; pgrep -l emacs
Mon Oct  9 23:50:43 MST 2017

Now, start a clientless daemon:

me@it: ~ $ date ; emacs --daemon &
Mon Oct  9 23:51:05 MST 2017
... console spew follows ...
me@it: ~ $ date ; pgrep -l emacs
Mon Oct  9 23:51:20 MST 2017
8467 emacs

I can cleanly query this daemon process (unfortunately not by process#, but that's another question) with

me@it: ~ $ date ; emacsclient --eval '(if (daemonp) (message "true") (message "false"))'
Mon Oct  9 23:53:29 MST 2017
"true"

That, to me is "working as expected": particularly,

  • response is correct
  • no side effects

Kill that daemon (and cleanup after it--see this question for details):

me@it: ~ $ date ; pkill -9 emacs
Mon Oct  9 23:57:03 MST 2017
me@it: ~ $ date ; find ~/.emacs.d/ -name '*lock*'
Mon Oct  9 23:57:07 MST 2017
/home/me/.emacs.d/personal/.emacs.desktop.lock
me@it: ~ $ date ; find ~/.emacs.d/ -name '*lock*' | xargs rm
Mon Oct  9 23:57:17 MST 2017

Start a classic Emacs:

me@it: ~ $ date ; emacs --debug-init &
Mon Oct  9 23:57:47 MST 2017
me@it: ~ $ date ; pgrep -l emacs
Mon Oct  9 23:57:57 MST 2017
8692 emacs

Now try to query this classic process: very messy:

me@it: ~ $ date ; emacsclient --eval '(if (daemonp) (message "true") (message "false"))'
Mon Oct  9 23:58:19 MST 2017
emacsclient: connect: Connection refused

After that, I get my normal daemon startup console spew (which is a lot, since I'm running a Prelude config), followed by

Starting Emacs daemon.
Emacs daemon should have started, trying to connect again

ending with output that is only technically correct:

"true"

I.e., instead of telling me that the classic process is not a daemon, this creates me a daemon then tells me ... it's a daemon :-(

me@it: ~ $ date ; pgrep -l emacs
Mon Oct  9 23:58:35 MST 2017
8692 emacs
8747 emacs

So I guess I can use the above process to discriminate between classic and daemon processes: if I get yet another process name=emacs, the 1st/tested process was classic, else daemon. But how to discriminate from a commandline

  • not from within Emacs
  • without non-trivial side effects, like creating a new/unwanted process

between classic and daemon processes?

1 Answer 1

0

The following is more of a workaround, but in the absence of a "real fix" (which I suspect will require better support from Emacs), it's what I got, and it works. (I will upvote any "real answers" subsequently provided.)

Workaround: use a bogus alternate-editor, and handle the error thrown by a "classic" Emacs. (I use true == /bin/true , but suspect that any non-interactive executable will work.) See working bash script using this approach, and code testing that script. Alternately: save following code to a file (below I use /tmp/test.sh):

#!/usr/bin/env bash

TEST_OUT="$(emacsclient --alternate-editor='true' --\eval '(if (daemonp) (message "true") (message "false"))' 2> /dev/null)"
## Note all my attempts to parameterize the above failed due to `bash` quoting problems.

if   [[ -z "${TEST_OUT}" ]] ; then
    echo 'classic'
    exit 0
elif [[ "${TEST_OUT}" == '"true"' ]] ; then
    echo 'daemon'
    exit 0
else
    >2& echo 'unknown'
    exit 2
fi

exit 1 # should never be reached

Testcases:

  1. daemon

    me@it: ~ $ date ; emacs --daemon &
    Thu Oct 12 22:08:01 MST 2017
    [1] 5935
    ... console spew follows ...
    me@it: ~ $ date ; pgrep -l emacs
    Thu Oct 12 22:08:25 MST 2017
    5935 emacs
    me@it: ~ $ date ; /tmp/test.sh
    Thu Oct 12 22:08:29 MST 2017
    daemon
    
  2. cleanup

    me@it: ~ $ date ; pkill -9 emacs
    Thu Oct 12 22:08:35 MST 2017
    me@it: ~ $ date ; find ~/.emacs.d/ -name '*lock*'
    Thu Oct 12 22:08:40 MST 2017
    /home/me/.emacs.d/personal/.emacs.desktop.lock
    me@it: ~ $ date ; find ~/.emacs.d/ -name '*lock*' | xargs rm
    Thu Oct 12 22:08:45 MST 2017
    me@it: ~ $ date ; pgrep -l emacs
    Thu Oct 12 22:08:49 MST 2017
    
  3. classic

    me@it: ~ $ date ; emacs --debug-init &
    Thu Oct 12 22:09:05 MST 2017
    [1] 18224
    me@it: ~ $ date ; pgrep -l emacs
    Thu Oct 12 22:09:44 MST 2017
    18224 emacs
    me@it: ~ $ date ; /tmp/test.sh
    Thu Oct 12 22:09:48 MST 2017
    classic
    

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.