jscheid/prettier.el

Emacs gets stuck with "Prettier syncing config"

swarnendubiswas opened this issue · 27 comments

Describe the bug

  1. Start Emacs
  2. Switch to a project using say projectile.
  3. Select a .md file to open.
  4. Emacs gets stuck with "Prettier syncing config" message echoed in the minibuffer.

Link to M-x prettier-info output

Running M-x prettier-info on a .md buffer also causes Emacs hang.

To Reproduce

Emacs - 27.0.91 (through snap)
Ubuntu - 18.04
Node - 14.5.0
Prettier - 2.0.5

I also have nvm installed and I use exec-path-from-shell in my Emacs config.

See description.

Expected behavior

The .md file should open as expected. It seems prettier cannot be accessed, is it?

Additional context

I do not see the problem if I open a different project file first and then open a .md file.

Is there anything interesting in *Messages* or the *prettier (local)* buffer?

Does this also happen if you don't use projectile?

Yes, I could reproduce it without projectile. My Emacs hangs so I cannot see any output from prettier buffer. I can recover by quitting with C-g. The Messages buffer shows the following.

Starting new Ispell process /usr/bin/aspell with en_US dictionary...done
[yas] Prepared just-in-time loading of snippets successfully.
Loading /home/swarnendu/.emacs.d/tmp/recentf...done
Please type y, n, or !: !
Loading /home/swarnendu/.emacs.d/tmp/custom.el (source)...done
Saving file /home/swarnendu/github/dotemacs/tmp/custom.el...
Wrote /home/swarnendu/github/dotemacs/tmp/custom.el
Saving file /home/swarnendu/github/dotemacs/tmp/recentf...
Wrote /home/swarnendu/github/dotemacs/tmp/recentf
markdown-mode math support enabled
Prettier syncing config
markdown-mode math support enabled
Quit

After C-g, is there no *prettier (local)* buffer?

No. How can I help debug the issue?

Thanks. First, could you try running emacs without config (ie. emacs -q) and then manually loading prettier, and see if that works? Something like:

(require 'package)
(package-initialize)
(require 'prettier)
(find-file "test.md")
(prettier-info)

I can also try and reproduce this here in a VM. Do you remember how exactly you installed emacs and node on top of Ubuntu 18?

Also, what happens when you run this:

(shell-command-to-string "node --version")

Does it hang as well?

I've tried reproducing this without much success: https://github.com/jscheid/prettier-el-vagrant

The issue somehow got fixed yesterday. I have been trying to reproduce it since but I haven't been able to.

(shell-command-to-string "node --version") is

v14.5.0

Ok, I'll close this then. Feel free to reopen if you find a way to reproduce.

Instead I now get a different error and on multiple machines.

/home/swarnendu/github/dotemacs/README.md: Error: Cannot find prettier anywhere

The suggested solution in issue #33 (setenv "NODE_PATH" "/usr/local/lib/node_modules") resolves it.

I was getting a strange error related to this mode, and decided to clean the slate by doing unload-feature on prettier, then (load "prettier"). At that point, Emacs was hung for a bit with the "Prettier syncing config" message and eventually recovered, at which point I did global-prettier-mode. I grabbed the following from the *Messages* buffer:

Prettier restart complete.
Prettier pre-warming...
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming... [2 times]
Prettier syncing config
Prettier pre-warming...
Global Prettier mode enabled

I had just closed most files, so this was more than the number of buffers I had open.

Just posting in case this provides any clues.

I can reproduce this with a running emacs, but not with emacs -q. It hangs here according to edebug:

(iter-do (command iter)

What should I try next?

Hi @aspiers, what's in the *prettier* buffer?

There is no such buffer.

parsers is nil, is that right?

I see *prettier (local)* while mid-edebug, but it's empty, and as soon as I go beyond the above line, everything hangs, and C-g results in that buffer vanishing.

If I use macroexpand to step through the iter-do, it gets to:

    (unwind-protect
        (progn
          (let
              (command iter-do-result1647
                       (iter-do-iterator-done1644 nil)
                       (iter-do-iterator1646 iter))
            (while
                (not iter-do-iterator-done1644)
              (condition-case iter-do-condition1645
                  (setf command
                        (iter-next iter-do-iterator1646))

and hangs on evaluation of iter-do-iterator1646. I have no idea what any of that is supposed to do, way too much meta-programming to understand.

I can now reproduce on two separate machines.

I can now reproduce on two separate machines.

That's great news.

Yes, I meant the *prettier (local)* buffer.

I don't think stepping through the code with edebug is going to help much. It's 98% likely to be a problem at the protocol (sub-process connection) level. For example, you can probably make the Elisp side hang quite easily by kill -9ing the subprocess.

When the hang happens, is the subprocess still alive?

Is there a way to turn your reproduction into a test case, maybe a Dockerfile?

Oh I see. The subprocess is alive but apparently stuck, or at least doing nothing:

$ pstree -p 27051
emacs-gtk,27051
  |-aspell,13899 -a -m -B --encoding=utf-8
  |-emacsql-sqlite,6946 /home/adam/.emacs.d/forge-database.sqlite
  |-node,13585 --eval 6>Number(process.version.split(/[v.]/)[1])&&process.exit(3);var b=require,f=b("zlib").gunzipSync,g=b("vm"),h=b("fs"),k=new g.Script(f(Buffer.from(function(l,c){for(var d=Buffer.alloc(c),a=0;a<c;){var e=h.readSync(l,d,a,c-a,null);if(0>=e)throw Error("EOF");a+=e}return d}(0,Number(process.argv[1])).toString("ascii"),"base64")).toString("utf-8"));k.runInThisContext()(k);\012 8650
  |   |-{node},13586
  |   |-{node},13587
  |   |-{node},13588
  |   |-{node},13589
  |   |-{node},13590
  |   `-{node},13591
  |-{emacs-gtk},27058
  |-{emacs-gtk},27063
  |-{emacs-gtk},27068
  `-{emacs-gtk},27074

$ strace -ff -p 13585
strace: Process 13585 attached with 7 threads
[pid 13589] futex(0x5dcd2c0, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME, 0, NULL, FUTEX_BITSET_MATCH_ANY <unfinished ...>
[pid 13587] futex(0x5dcd2c0, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME, 0, NULL, FUTEX_BITSET_MATCH_ANY <unfinished ...>
[pid 13591] futex(0x44a9640, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME, 0, NULL, FUTEX_BITSET_MATCH_ANY <unfinished ...>
[pid 13590] futex(0x5dcd2c0, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME, 0, NULL, FUTEX_BITSET_MATCH_ANY <unfinished ...>
[pid 13586] epoll_wait(9,  <unfinished ...>
[pid 13585] epoll_wait(13,  <unfinished ...>
[pid 13588] futex(0x5dcd2c0, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME, 0, NULL, FUTEX_BITSET_MATCH_ANY

I very much doubt I can reproduce in Docker, since the problem vanished as soon as I restarted one of my emacs processes. I tend to run them for weeks or months at a time, which I guess may even be a contributing factor.

My Emacs also runs for a long time (with prettier.el and a sub-process). Maybe not months, but several weeks isn't unheard of.

Tricky, not entirely sure where to go from here... FWIW I'm using it all the time, in long-running Emacs processes, and it appears rock-solid to me. I can't remember the last time it hung on me. You're using the latest version obviously?

Hrm, I definitely had the latest release checked out, but I just did eval-buffer on prettier.el and the issue vanished, so maybe it was a question of old byte code lingering in my long-running emacs.

I think straight.el doesn't provide any way to reload an updated package, which is probably because emacs itself doesn't have real namespaces and therefore no way to disentangle variables and functions in an old version from the global namespace and "unload" them before reloading a newer version. So maybe that's how I ended up with the latest release checked out but not in my emacs VM.

Ah! Hmm, that's not ideal. I did write #73 hoping that it would help with upgrading in a long-running session but I haven't ever tested it with straight.el, that might be worth doing at some point. Anyway, I'm glad it's working better now for you!

Me too, thanks a lot for your support!