I look for ideas, how to diagnose reason of Emacs freezes (by which I mean taking 100% CPU and being irresponsive for some time). This question is not about any specific case¹ but about approach…

Is it possible to ask Emacs „show me/dump somewhere current stack trace(s) of all currently running Lisp thread(s)”? Or maybe „dump stack trace very 10 seconds somewhere”? Sth I could do to check what's going on once I see my emacs frozen…

Or, is it possible to enable some kind of global profiling (with output put to some disk file at regular intervals) so I could look there for likely culprit?

Or, is there any other trick? What would you do if you saw misbehaving Emacs and bisecting all libraries would not seem promising²?

¹ Currently I experience two problems:

  • from time to time, Ctrl-Y takes 10-30 seconds (and Emacs takes 100% some CPU core during this time),

  • from time to time Emacs turns sluggish (albeit works more or less properly), and it turns out one of Emacs processes takes 100% of CPU

Both surely are related to some rogue lisp code (I load plenty of melpa modules) or caused by unexpected relationship of some modules, and it is fairly likely that it is my very specific configuration what makes them appear.

² My current problem appeared after I made major package-update which installed many updated versions of various packages and to which I also added a couple of new modules. Bisecting that doesn't seem promising as sometimes it takes a day or two before the problem appears, reverting to old versions for good also is not sth I would like…

  • See also this question and this question. – legoscia Apr 21 '15 at 11:00
  • ''toggle-debug-on-quit'' is useful and I use it often (and also tried here), but in those cases it brings nothing as my attempts to Ctrl-G are ignored in the first case (emacs remains frozen for some time whether I keep pressing Ctrl-G or not), and don't impact the problem in second (whatever background task is taking 100% cpu, Ctrl-G does not interrupt it but impacts „frontend“ task at hand…). I did not know about SIGUSR2, will give it a try once I face problem again. – Mekk Apr 21 '15 at 11:13
  • As I wrote below SIGUSR2 seems to be what I looked for. – Mekk Apr 21 '15 at 11:36
  • As odd as it may sound, there is still no concurrency support in Elisp, so there's only ever one Elisp thread. – Stefan Apr 21 '15 at 13:16

(Idea taken from one of the questions suggested by legoscia)

It looks like killing emacs with SIGUSR2 does exactly what I looked for, at least in the first (hang on yank) case (which politely reappeared soon after I got this advice). I am yet to understand the stacktrace³, but killing emacs with SIGUSR2 nicely interrupted the freeze and dumped stacktrace.

So, the answer to my question is kill -USR2 «emacspid» (or, easier, htop, p, k, 12, Enter).

³ Here is what I got (byte code commented out as it contained unreadable characters): Debugger entered--entering a function: * command-error-default-function((quit) "" nil) #<subr recursive-edit>() byte-code(...) ad-Advice-recursive-edit(#<subr recursive-edit>) apply(ad-Advice-recursive-edit #<subr recursive-edit> nil) recursive-edit() debug(error (quit)) accept-process-output() semantic-c-lexer(778 1374 nil nil) semantic-lex(778 1374 nil) semantic-parse-region-default(778 1374 nil nil nil) semantic-parse-region-c-mode(778 1374 nil nil nil) semantic-parse-region(778 1374 nil) semantic-edits-incremental-parser-1() byte-code(...) semantic-parse-changes-default() semantic-parse-changes() semantic-fetch-tags() byte-code(...) semantic-idle-scheduler-refresh-tags() byte-code(...) semantic-idle-core-handler() semantic-idle-scheduler-function() apply(semantic-idle-scheduler-function nil) byte-code(...) timer-event-handler([nil 0 1 0 t semantic-idle-scheduler-function nil idle 0]) Still semantic is not necessarily guilty as while all above is semantic and most commented bytecodes too, the deepest byte-code mentions various persp- functions, mayhaps semantic triggers some event which persp binds too etc etc… Here is the readable part of it: byte-code("..." [persp-recursive G94967 persp-curr perspectives-hash old-hash ad--addoit-function persp-save boundp ((byte-code "..." [G94967 persp-recursive makunbound] 2)) copy-hash-table maphash #[(key new-persp) "..." [key old-hash persp cl-struct-perspective-tags v new-persp gethash 0 error "%s accessing a non-%s" persp-buffers perspective 2] 7] ad-return-value] 3)

  • If you want a backtrace without byte code, find the function definition with M-x find-function, evaluate it with C-M-x, and reproduce the problem again. The resulting backtrace will usually be detailed enough to find the exact line, though sometimes macro expansions can be confusing. – legoscia Apr 21 '15 at 11:40
  • 1
    The ad-Advice-recursive-edit indicates that some package advised recursive-edit, and advising is often tricky business which can introduce bugs. IIUC the advice is added by perspective, so I recommend you send this backtrace to the author of the Perspective package. – Stefan Apr 21 '15 at 13:14
  • Which function should I find ? persp-recursive? – Mekk Apr 21 '15 at 13:45
  • This worked perfectly for me. Funnily enough, in my case it also unbound everything in the global keymap except for q. I have no idea how that happened, but I did find out which function was generating an annoying message :) – Radon Rosborough Jun 18 '18 at 4:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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