Holen Sie sich programmgesteuert eine Rückverfolgung von Fehlern

12

Wenn im Emacs-Lisp-Code ein Fehler gemeldet wird und dies der Fall debug-on-errorist t, erhalte ich einen Rückverfolgungspuffer, mit dem sich leicht herausfinden lässt, wo der Fehler aufgetreten ist. Bei Fehlern, die bei der asynchronen Verarbeitung einer Antwort aus dem Netzwerk auftreten, wäre es jedoch ärgerlich, wenn der Rückverfolgungspuffer eingeblendet würde. Daher würde ich den Fehler lieber mit abfangen condition-caseund protokollieren.

Gibt condition-casees eine Möglichkeit, bei der Behandlung eines Fehlers in auf die Rückverfolgung zuzugreifen, wenn der Fehler auftritt? Das Aufrufen der backtraceFunktion ruft die Rückverfolgung des Codes im Handler ab, was nicht das ist, wonach ich suche.

(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
quelle
1
magithub-errorIch denke, meine Funktion macht etwas Ähnliches, aber ich bin gerade nicht an einem Computer. Es kann trotzdem helfen.
Sean Allred
1
Das ist ein generelles Problem bei jeder Sprache, die ihren Stack auf ähnliche Weise verwaltet. Eine Möglichkeit, dies zu handhaben, besteht darin, einen Fehler zu signalisieren, an den bereits Stapelinformationen angehängt sind. Dh in Ihrem Fall müssten Sie do-something-that-might-faileinen Stack-Trace generieren und ihn an den Fehler anhängen, den er verursacht.
wvxvw
1
debbugs.gnu.org/cgi/bugreport.cgi?bug=24617#8 hat einen Vorschlag (habe es nicht selbst ausprobiert)
Npostavs

Antworten:

1

Am einfachsten ist es, einen eigenen Debugger in der Umgebung zu erstellen, in der der Fehler auftritt. Das geht ungefähr so:

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

Die letUmgebung verwendet diese benutzerdefinierte Debugger-Funktion my-debuggerfür die Dauer des darin enthaltenen Codes. Wenn Sie also auf einen nicht behandelten Fehler stoßen, wird der "Debugger" ausgeführt, der im Wesentlichen nur die Nachricht druckt. Dieser Debugger wird in der Umgebung ausgeführt, in der der Fehler aufgetreten ist. In Ihrem Backtrace erfahren Sie also, was passiert ist.

Hinweis: Dieser Code hat zwei (lösbare) Probleme, die ich für Sie hinterlassen werde. Zunächst möchten Sie wahrscheinlich die ersten Stapelrahmen entfernen, da sie sich auf den Aufruf von beziehen backtrace. Zweitens erhalten Sie eine Meldung, die auf den Fehler hinweist (im obigen Fall beispielsweise "let: Die Funktionsdefinition von Symbol ist ungültig: foobar"). Weder sind riesige Probleme, aber ich wollte meine Antwort nicht verwirren.

Cyberbisson
quelle