6

I use emacs in the terminal, typically with many emacs instances running at once in different tabs. This is a perfect use case for emacsclient, but it has always had various glitches that have stopped me from using it. In particular, sometimes one client will "block" the other, preventing it from doing anything. It looks like things work better in emacs 24.4, but it still happens.

For instance, if I start two clients, and run M-g M-g in one, to get the "Goto line" entry, the other client will be completely locked down until I quit in the first one.

I am using emacs 24.4 compiled without windowed support in Mac OS X 10.10 (in iTerm 2). I can reproduce it by starting emacs --daemon -Q. If you want the exact emacs binary I am using, download Miniconda for OS X and run conda install -c asmeurer emacs.

asmeurer
  • 1,572
  • 12
  • 32
  • FWIW, I've since given up on trying to run multiple emacsclients at once. Instead, I start one emacs server per terminal tab using --socket-name=emacs-$TTY (see https://github.com/asmeurer/dotfiles/blob/master/bin/emacs-server-start for the exact script I use). Since I only use a handful of terminal tabs and never close them, this works well for me. – asmeurer Nov 24 '23 at 08:41

3 Answers3

5

No, you can't "prevent emacsclient from blocking other [emacsclient] instances", because that's not what's happening.

emacsclient isn't running any elisp at all, so it's not the cause of the blockage. The Emacs server is running the elisp code, and Emacs is single-threaded -- so if the server thread is blocked then none of the clients will be receiving any output. There's nothing that a client can do about that.

You can, as mentioned in the comments, run multiple independent servers side by side. The simplest way to do this is via the --daemon=NAME command line argument:

emacs --daemon=foo
emacs --daemon=bar
emacsclient --socket-name=foo
emacsclient --socket-name=bar

or short-cut it to:

emacsclient -a "" --socket-name=foo
emacsclient -a "" --socket-name=bar
phils
  • 50,977
  • 3
  • 79
  • 122
  • I guess this is workable. I can add export TTY=$(basename \tty`)in my bash profile and use--socket-name=$TTY`. – asmeurer Nov 07 '14 at 17:25
  • A disadvantage here is that I no longer get any shared state if I open the same file in different instances. I would still very much appreciate an actual solution to this problem. – asmeurer Nov 07 '14 at 17:31
  • Even with this solution, emacsclient (or the server, whatever) will still sometimes completely block all clients, forcing me to find the PID for the server process and kill -9 it. – asmeurer Nov 07 '14 at 20:54
  • And just now I've got a server that even when I kill it, every time it restarts it immediately blocks, making it unusable. – asmeurer Nov 07 '14 at 21:18
  • There is certainly no solution to Emacs being single-threaded, short of re-writing it to be multi-threaded (and there are many good reasons why this has never happened). – phils Nov 09 '14 at 05:35
  • I don't follow why being single threaded means it has to block sometimes. It doesn't always block, even when I am editing the same buffer in two different clients – asmeurer Nov 09 '14 at 20:01
  • Emacs has a command loop which can execute one command at a time. When you are "editing", each command (e.g. inserting a character) takes very little time. When Emacs is prompting you for input, it is in the middle of executing a command, and it cannot continue the command until you have provided the necessary input. (Maybe. This isn't the whole story, and I've really never delved into this part of Emacs, so I might be incorrect; but it should at least indicate how regular editing is a different scenario). – phils Nov 09 '14 at 20:52
  • It's still locking up even with a server for each terminal session sometimes. I've asked a new question for it http://emacs.stackexchange.com/questions/3370/emacs-daemon-frozen-when-started-with-emacsclient-file – asmeurer Nov 10 '14 at 23:50
  • 1
    This is not quite correct. Yes, everything runs on the server, and yes, the server is single threaded, but there is no technical reason for the minibuffer to block the server loop. You can see this in action by switching from the mini buffer to a different buffer while leaving the mini buffer open (with a partial command in it). There's got to be some internal lock getting set which blocks other clients (or the server itself if using server-start) while a minibuffer is open (focused or not). I'll see if I can find it and defadvice my way around it. – Perkins Feb 20 '20 at 02:46
3

Got it! Good news is it works perfectly to have the minibuffer active in one window and type in another*. Bad news is it requires recompiling emacs, as it's the C-implementation of read_minibuf which forces single-kboard. It's probably possible to reimplement the minibuffer largely in elisp, intercepting most calls to it, but that would be somewhat complex...

Anyway, with emacs-26, the line to comment is src/minibuf.c:480,

temporarily_switch_to_single_kboard (XFRAME (mini_frame));

*I've tested it some, no promises it won't break things in subtle ways. Also note that the minibuffer uses a single, global input state, so opening the mini buffer closes any mini buffers opened in other frames. If you enable recursive-minibuffers, you do get your partial command back when the other person is done, but there's still likely to be some odd behaviour. Also, things like find-file use switch_to_single_kboard too.

I'll probably follow up on the mailing list to see if this can get turned into a proper customizable variable, possibly disabling all switch_to_single_kboard calls, as it's a must for sharing an emacs instance on a joint project.

If you want to disable single-keyboard mode everywhere, insert return; on a new line at src/keyboard.c:883.

As requested, a diff...

*** src/minibuf.c       2020-02-20 17:27:13.472345220 -0800
--- src.orig/minibuf.c  2020-02-20 17:26:20.164343599 -0800
***************
*** 478,482 ****
      Fraise_frame (mini_frame);

<   //temporarily_switch_to_single_kboard (XFRAME (mini_frame));

    /* We have to do this after saving the window configuration
--- 478,482 ----
      Fraise_frame (mini_frame);

>   temporarily_switch_to_single_kboard (XFRAME (mini_frame));

        /* We have to do this after saving the window configuration

And the other diff

*** src/keyboard.c      2020-02-20 17:27:01.452344855 -0800
--- src.orig/keyboard.c 2020-02-20 17:26:15.040343443 -0800
***************
*** 881,885 ****
  temporarily_switch_to_single_kboard (struct frame *f)
  {
<   return false;
    bool was_locked = single_kboard;
--- 881,884 ----
Perkins
  • 131
  • 2
  • 1
    That sounds like something I won't be trying :) Could you please show actual diffs in your answer? Only showing line numbers isn't nearly as useful. – phils Feb 20 '20 at 05:38
  • Note that this produces poor results in emacs-27 (and probably later), since partial commands are stored (and completed) globally. Then again, that's an issue even without unlocking multi-keyboard mode in the minibuffer. – Perkins Feb 22 '20 at 18:02
  • A year later, I've found and patched the emacs-27+ bug that breaks multiple keyboards. IfI ever hear back from the FSF about my copyright assignment I'll even get that fix included... So far, crickets. – Perkins Jan 31 '21 at 01:34
  • Awesome; cheers. They're normally fairly responsive, so if you haven't heard anything within a few days, definitely chase that up (either directly, or on the emacs-devel mailing list). I'm sure that someone will sort you out. – phils Jan 31 '21 at 19:38
  • What is the bug that breaks multiple keyboards on 27+? – Sam Brightman Jan 18 '23 at 20:53
1

I frequently run into the problem of emacsclient instances being blocked, sometimes accompanied by an error message like "*ERROR*: Terminal 2 is locked, cannot read from it". A solution for unblocking it is to run:

emacsclient -e '(top-level)'

The problem and solution are discussed in more detail in https://github.com/emacs-mirror/emacs/blob/master/admin/notes/multi-tty and have to do with a session being stuck in a minibuffer prompt or recursive editing mode.

  • 1
    Welcome to emacs.sx! Anyone else dealing with recursive editing and so on might find this Emacs Elements video useful: https://www.youtube.com/watch?v=SD8myoNYnss -- it's a nice intro to the various "get me out of here" things in emacs. – Dan Drake Nov 22 '23 at 12:13