LINUX.ORG.RU

Backtrace из condition'а

 ,


0

1

Привет лисперам,

А вот есть ли способ получить backtrace из прилетевшего condition'а? Например в виде строки (лучше, конечно, списка). Лучше переносимо, но сгодится и sbcl-way.

Чтот пока не нахожу. trivial-backtrace дает бэктрейсы точки вызова (print-backtrace err), а не точки выброса этого самого err. Есть мысль поискать в SWANK, но беглый осмотр пока результатов не дал.

★★★★★

Но ведь и signal, и error принимают список аргументов. Заведи в condition слот для бэктрэйса, и инициализируй его при вызове signal/error.

anonymous
()

получить backtrace из прилетевшего condition'а?

Большого смысла в этой затеи нет, только бывает нужно когда на продакшене нужно сформировать баг-репорт файл в который выплевывать ошибки для отправки суппорту, а доступа к запушенному образу для отладки нет.

При нормальной разработке, в среде лиспа (под SWANK или другой) будет доступен полноценный дебаггер, в котором отлавливать ошибки и нужно, включая вывод бэктрэйса.

Ну а если уж очень нужно, то можно сделать так (необходимо компилировать при этом с самым высоким уровнем debug и safety, иначе некоторые вызовы могут заинлайнится компилятором):

;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; indent-tabs-mode: nil; external-format: utf-8; -*-

(in-package #:cl-user)

(declaim (optimize safety debug (speed 0)))
(declaim (notinline my-fun0 my-fun1 my-fun2))

(defun my-fun0 ()
  (error "fuckup"))

(defun my-fun1 ()
  (my-fun0))

(defun my-fun2 ()
  (my-fun1))

(defun test-my-fun ()
  (handler-bind ((error
                   #'(lambda (condition)
                       (trivial-backtrace:print-backtrace condition))))
    (my-fun2)))

SWANK debugger:

fuckup
   [Condition of type SIMPLE-ERROR]

Restarts:
 0: [RETRY] Retry SLIME REPL evaluation request.
 1: [*ABORT] Return to SLIME's top level.
 2: [ABORT] Abort thread (#<THREAD "repl-thread" RUNNING {C4CC5D9}>)

Backtrace:
  0: (MY-FUN0)
  1: (MY-FUN1)
  2: (MY-FUN2)
  3: (TEST-MY-FUN)
  4: (SB-INT:SIMPLE-EVAL-IN-LEXENV (TEST-MY-FUN) #<NULL-LEXENV>)
  5: (EVAL (TEST-MY-FUN))
 --more--

Вывод trivial-backtrace для LispWorks и SBCL (много инфы поскипано):


; SBCL:
;
; 4: ((FLET #:LAMBDA11 :IN TEST-MY-FUN) #<SIMPLE-ERROR "fuckup" {AC5FC91}>)
; 5: (SIGNAL #<SIMPLE-ERROR "fuckup" {AC5FC91}>)
; 6: (ERROR "fuckup")
; 7: (MY-FUN0)
; 8: (MY-FUN1)
; 9: (MY-FUN2)
; 10: (TEST-MY-FUN)
; 11: (SB-INT:SIMPLE-EVAL-IN-LEXENV (TEST-MY-FUN) #<NULL-LEXENV>)
; 
; 
; LispWorks:
; 
; Call to ERROR {offset 67}
;   SYSTEM::ESTRING : "fuckup"
;   SYSTEM::EARGS   : NIL
; 
; Call to MY-FUN0 {offset 34}
; 
; Call to MY-FUN1 {offset 29}
; 
; Call to MY-FUN2 {offset 29}
; 
; Call to TEST-MY-FUN {offset 180}
;   DBG::G                                    : #<Function 1 subfunction of TEST-MY-FUN  200BCDD2>
;   CONDITIONS::*HANDLER-CLUSTERS*  {Special} : (((ERROR . #<Function 1 subfunction of TEST-MY-FUN 200BCDD2>)) ((T . #<Closure 2 subfunction of SWANK:EVAL-FOR-EMACS 1CEFEA8A>)) ((SWANK::SWANK-ERROR . #<Function 3 subfunction of SWANK::HANDLE-REQUESTS 2237BF52>)) ((SWANK::SWANK-ERROR . #<Closure 2 subfunction of SWANK::HANDLE-REQUESTS 1CEFEDEA>)))

gensym ★★
()
Ответ на: комментарий от anonymous

Но ведь и signal, и error принимают список аргументов. Заведи в condition слот для бэктрэйса, и инициализируй его при вызове signal/error.

Да, конечно так можно для своих condition'ов, не для произвольных.

Sectoid ★★★★★
() автор топика
Ответ на: комментарий от gensym

Большого смысла в этой затеи нет, только бывает нужно когда на продакшене нужно сформировать баг-репорт файл в который выплевывать ошибки для отправки суппорту, а доступа к запушенному образу для отладки нет.

Для меня смысл очень большой и именно в этом: после того как у кастомера где-то произошел факап — понять где. Между факапом и его анализом может пройти до месяца времени (и не один reload приложения). Потому трейс очень нужен.

За пинок в сторону inline — спасибо, похоже у меня trivial-backtrace возвращал ересь именно по этой причине.

Sectoid ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.