jscheid / prettier.el

Prettier code formatting for Emacs.
GNU General Public License v3.0
167 stars 12 forks source link

Emacs gets stuck with "Prettier syncing config" #34

Closed swarnendubiswas closed 4 years ago

swarnendubiswas commented 4 years ago

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.

jscheid commented 4 years ago

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

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

swarnendubiswas commented 4 years ago

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
jscheid commented 4 years ago

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

swarnendubiswas commented 4 years ago

No. How can I help debug the issue?

jscheid commented 4 years ago

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)
jscheid commented 4 years ago

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?

jscheid commented 4 years ago

Also, what happens when you run this:

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

Does it hang as well?

jscheid commented 4 years ago

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

swarnendubiswas commented 4 years ago

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
jscheid commented 4 years ago

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

swarnendubiswas commented 4 years ago

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.

earthlyreason commented 3 years ago

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.

aspiers commented 3 years ago

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

https://github.com/jscheid/prettier.el/blob/85c9349de2730b71c5796e342d67efee34faa9ed/prettier.el#L1134

What should I try next?

jscheid commented 3 years ago

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

aspiers commented 3 years ago

There is no such buffer.

aspiers commented 3 years ago

parsers is nil, is that right?

aspiers commented 3 years ago

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.

aspiers commented 3 years ago

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.

aspiers commented 3 years ago

I can now reproduce on two separate machines.

jscheid commented 3 years ago

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?

aspiers commented 3 years ago

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
aspiers commented 3 years ago

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.

jscheid commented 3 years ago

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.

jscheid commented 3 years ago

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?

aspiers commented 3 years ago

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.

jscheid commented 3 years ago

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!

aspiers commented 3 years ago

Me too, thanks a lot for your support!