Programowo uzyskaj ślad po błędzie

12

Jeśli w kodzie Emacs Lisp zasygnalizowany jest błąd, debug-on-errorpojawia tsię bufor śledzenia, który ułatwia ustalenie, gdzie wystąpił błąd. Jednak w przypadku błędów, które występują podczas asynchronicznego przetwarzania odpowiedzi z sieci, denerwujące byłoby pojawienie się bufora śledzenia wstecznego, więc wolę wychwycić błąd condition-casei zarejestrować go.

Kiedy więc zajmuję się błędem condition-case, czy istnieje sposób na uzyskanie dostępu do śledzenia wstecznego w momencie wystąpienia błędu? Wywołanie backtracefunkcji pobiera ślad kodu wewnątrz modułu obsługi, czego nie szukam.

(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
źródło
1
magithub-errorMyślę, że moja funkcja robi coś podobnego, ale nie jestem teraz przy komputerze. Może to pomóc niezależnie.
Sean Allred,
1
Jest to ogólny problem z każdym językiem, który zarządza swoim stosem w podobny sposób. Sposobem na poradzenie sobie z tym jest zasygnalizowanie błędu, do którego dołączono już informacje o stosie. Tj. W twoim przypadku do-something-that-might-failwygenerowałbyś śledzenie stosu i dołączasz go do zgłaszanego błędu.
wvxvw
1
debbugs.gnu.org/cgi/bugreport.cgi?bug=24617#8 ma sugestię (sam tego nie próbowałem)
npostavs

Odpowiedzi:

1

Najprościej jest stworzyć własny debugger w środowisku, w którym występuje błąd. To idzie mniej więcej tak:

(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Środowisko wykorzystuje tę niestandardową funkcję debuggera my-debuggerna okres kodu wewnątrz niego, więc jeśli wystąpi błąd un-obsłużony, „debugger” będzie działać, co w zasadzie tylko wypisuje komunikat. Ten debugger działa w środowisku, w którym wystąpił błąd, więc ślad śledzenia powie ci, co się stało.

Uwaga: w tym kodzie występują dwa (możliwe do rozwiązania) problemy, które pozostawię tobie. Najpierw prawdopodobnie chcesz usunąć kilka pierwszych ramek stosu, ponieważ odnoszą się one do wywołania backtrace. Po drugie, otrzymasz także komunikat wskazujący błąd (na przykład w powyższym przypadku „let: definicja funkcji symbolu jest nieważna: foobar”). Nie są to też duże problemy, ale nie chciałem zabłocić mojej odpowiedzi.

cyberbisson
źródło