Получить трассировку от ошибки программно

12

Если сигнализируется ошибка в коде Emacs Lisp, и debug-on-errorэто t, я получаю трассировку буфер , который позволяет легко выяснить , где произошла ошибка. Однако, для ошибок, возникающих при асинхронной обработке ответа от сети, было бы неприятно иметь всплывающий буфер обратной трассировки, поэтому я бы предпочел перехватить ошибку condition-caseи записать ее в журнал.

Итак, когда я обрабатываю ошибку в condition-case, есть ли способ получить доступ к обратному следу в точке ошибки? Вызов backtraceфункции возвращает след кода в обработчике, а это не то, что я ищу.

(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))))))
legoscia
источник
1
magithub-errorЯ думаю, что моя функция похожа на эту, но сейчас я не за компьютером. Это может помочь независимо.
Шон Оллред
1
Это общая проблема с любым языком, который управляет своим стеком аналогичным образом. Способ справиться с этим - сообщить об ошибке, к которой уже прикреплена информация стека. Т.е. в вашем случае вы должны do-something-that-might-failсгенерировать трассировку стека и прикрепить ее к возникающей ошибке.
wvxvw
1
У debbugs.gnu.org/cgi/bugreport.cgi?bug=24617#8 есть предложение (я сам не пробовал)
npostavs

Ответы:

1

Проще всего создать собственный отладчик в среде, в которой происходит ошибка. Это выглядит примерно так:

(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!

letСреда использует пользовательскую функцию отладчика my-debuggerдля длительности коды внутри него, так что если вы столкнулись ошибки не-трогать, «отладчик» будет работать, который по сути просто выводит сообщение. Этот отладчик работает в среде, где произошла ошибка, поэтому ваша обратная трассировка сообщит вам, что произошло.

Примечание. В этом коде есть две (решаемые) проблемы, которые я оставлю вам. Во-первых, вы, вероятно, захотите удалить первые несколько стековых фреймов, так как они относятся к вызову backtrace. Во-вторых, вы получите сообщение, также указывающее на ошибку (например, в приведенном выше случае «let: определение функции Symbol void: foobar»). Это не огромные проблемы, но я не хотел запутывать свой ответ.

cyberbisson
источник