Obter backtrace de erro programaticamente

12

Se um erro é sinalizado no código Emacs Lisp, e debug-on-erroré t, eu recebo um buffer de rastreamento que faz com que seja fácil de descobrir onde o erro ocorreu. No entanto, para erros que ocorrem durante o processamento de uma resposta da rede de forma assíncrona, seria irritante ter o buffer de backtrace pop-up, então prefiro capturar o erro condition-casee registrá-lo.

Então, quando estou lidando com um erro condition-case, existe uma maneira de obter acesso ao backtrace no ponto do erro? Chamar a backtracefunção obtém o retorno do código dentro do manipulador, o que não é o que estou procurando.

(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
fonte
1
Minha magithub-errorfunção faz algo semelhante a isso, eu acho, mas não estou em um computador no momento. Pode ajudar de qualquer maneira.
Sean Allred
1
Esse é um problema geral com qualquer idioma que gerencia sua pilha de maneira semelhante. Uma maneira de lidar com isso é sinalizar um erro que já possui informações de pilha anexadas a ele. Ou seja, no seu caso, você do-something-that-might-failgeraria o rastreamento de pilha e o anexaria ao erro gerado.
wvxvw
1
debbugs.gnu.org/cgi/bugreport.cgi?bug=24617#8 tem uma sugestão (não tentei me)
npostavs

Respostas:

1

A coisa mais fácil a fazer é criar seu próprio depurador no ambiente em que o erro ocorre. Isso é mais ou menos assim:

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

O letambiente usa essa função de depurador personalizada my-debuggerpela duração do código contido nele; portanto, se você encontrar um erro não tratado, o "depurador" será executado, o que basicamente apenas imprime a mensagem. Esse depurador é executado no ambiente em que ocorreu o erro, portanto, seu backtrace lhe dirá o que aconteceu.

Nota: Este código tem dois problemas (solucionáveis) que deixarei para você. Primeiro, você provavelmente deseja remover os primeiros quadros de pilha, pois eles pertencem à invocação de backtrace. Segundo, você receberá uma mensagem indicando o erro (por exemplo, no caso acima, "let: A definição da função do símbolo é nula: foobar"). Tampouco são problemas enormes, mas eu não queria confundir minha resposta.

cyberbisson
fonte