12

If an error is signalled in Emacs Lisp code, and debug-on-error is t, I get a backtrace buffer that makes it easy to figure out where the error occurred. However, for errors that occur while processing a response from the network asynchronously, it would be annoying to have the backtrace buffer pop up, so I'd rather catch the error with condition-case and log it.

So when I'm handling an error in condition-case, is there a way to get access to the backtrace at the point of the error? Calling the backtrace function gets the backtrace of the code inside the handler, which is not what I'm looking for.

(condition-case e
    (do-something-that-might-fail)
  (error
    (message "%s"
             ;; This gets the wrong backtrace!
             (with-temp-buffer
               (let ((standard-output (current-buffer)))
                 (backtrace)
                 (buffer-string))))))
  • 1
    My magithub-error function does something similar to this I think, but I'm not at a computer right now. It may help regardless. – Sean Allred Oct 28 '16 at 12:06
  • 1
    That's a general problem with any language that manages its stack in a similar way. A way to handle that is to signal an error which already has stack information attached to it. I.e. in your case, you'd have do-something-that-might-fail generate stack-trace and attach it to the error it raises. – wvxvw Oct 28 '16 at 12:14
  • 1
    debbugs.gnu.org/cgi/bugreport.cgi?bug=24617#8 has a suggestion (haven't tried it myself) – npostavs Oct 28 '16 at 19:34
1

The easiest thing to do is to create your own debugger in the environment in which the error occurs. That goes something like this:

(defun my-debugger (&rest debugger-args)
  (message "BACKTRACE: %s"
           (with-temp-buffer
             (let ((standard-output (current-buffer)))
               (backtrace)
               (buffer-string)))))

(let ((debugger #'my-debugger))
  (foobar)) ; Runs a function with no definition!

The let environment uses this custom debugger function my-debugger for the duration of the code inside it, so if you encounter an un-handled error, the "debugger" will run, which essentially just prints out the message. This debugger runs in the environment where the error occurred, so your backtrace will tell you what happened.

Note: This code has two (solvable) problems that I'll leave for you. First, you probably want to strip off first few stack frames, as they pertain to the invocation of backtrace. Second, you will get a message also indicating the error (for example, in the case above, "let: Symbol's function definition is void: foobar"). Neither are huge problems, but I didn't want to muddy my response.

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.