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?

TomRoche
  • 592
  • 3
  • 20

1 Answers1

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
    
TomRoche
  • 592
  • 3
  • 20