[hunchentoot-devel] Handling Lisp errors.

Andrei Stebakov lispercat at gmail.com
Mon Apr 16 01:21:02 UTC 2007


For error handling just supply your own function for *http-error-handler*.
>From there you can send an email as well or/and show a message to the user.
Something like this:

(setq *http-error-handler* 'my-error-handler)

(defun my-error-handler (return-code)
  (if (= +http-moved-temporarily+ return-code)
      (return-from my-error-handler))
  (let ((backtrace (get-backtrace 0))
    (session (start-session))) ;; retrieve stuff out of your session
    (send-email "Critical error" (format nil "RetCode: ~a, Backtrace: ~a"
return-code backtrace)) ;; My email function
    (with-html
      (:html
       (:head (:title "Error Page")
          (:link :rel "stylesheet" :type "text/css" :href *design-css*)
          (:script :language "JavaScript" :src *js-main-script* :type
"text/javascript" ""))
       (:body
    (:h2 "Sorry, a server-side error has occured.")))

Note that you need to make the size of the html code (css, javascript +
html) of the error page more than 512Bytes so that MS IE 7.0 would show your
information instead of its own message.

Andrew


On 4/15/07, Victor Kryukov <victor.kryukov at gmail.com> wrote:
>
> Hello list,
>
> I want to accomplish the following: every time a lisp error happens,
> the whole backtrace and some additional information is sent to my mail
> account.  The question is, what is the best way to do it with
> Hunchentoot? (I do know how to send email messages from lisp with the
> help of mel-base).
>
> The second question is: how do you use CLSQL thread-safely with
> Hunchentoot / SBCL? SBCL don't provide thread properties, so my first
> solution[1] was to create a hash-table and to assign each thread a
> connection, to check from every thread whether it already has a
> connection, and then to clean that hash-table periodically, closing
> connections for dead threads. That worked pretty well, but I was
> afraid of exhausting limit of database threads somehow, so I switched
> to the second solution.
>
> The second solution[2] is to open new connection every time I need to
> save something to database or read something from it, and to close it
> right after that. That of course solves connection limit problem
> (unless I have very many users simultaneously, which is not expected
> in the near term), however it's much slower.
>
> Anybody can share his/her strategy?
>
> Best regards,
> Victor.
>
> [1] http://paste.lisp.org/display/39787
> (defparameter *database-mutex* (sb-thread:make-mutex :name "database
> lock"))
> (defparameter *threads-connection* (make-hash-table))
>
> (defun setup-connection ()
>    (connect '("localhost" "lj" "victor" "victor")
>           :database-type :postgresql :if-exists :new))
>
> (defun db ()
>   (handler-case
>       (sb-thread:with-mutex (*database-mutex*)
>        (or (gethash sb-thread:*current-thread* *threads-connection*)
>            (setf (gethash sb-thread:*current-thread* *threads-connection*)
>                  (setup-connection))))
>     (error () (progn
>                (close-old-connections)
>                (db)))))
>
> (defun close-old-connections ()
>   (maphash #'(lambda (thread connection)
>               (unless (sb-thread:thread-alive-p thread)
>                 (clsql:disconnect :database connection)
>                 (remhash thread *threads-connection*)))
>           *threads-connection*))
>
> (let ((old-select (symbol-function 'clsql:select)))
>     (defun select (&rest args)
>      (let ((*default-database* (db)))
>        (apply old-select args))))
>
> (let ((old-insert-records (symbol-function 'insert-records)))
>     (defun insert-records (&rest args)
>      (apply old-insert-records :database (db) args)))
>
>
> [2] http://paste.lisp.org/display/39787#1
> (defun db ()
>   (connect *connection-spec*
>            :database-type :postgresql :if-exists :new))
>
> (let ((old-select (symbol-function 'clsql:select)))
>    (defun select (&rest args)
>      (let ((clsql:*default-database* (db)))
>        (prog1
>            (apply old-select args)
>          (disconnect :database clsql:*default-database*)))))
>
> (let ((old-insert-records (symbol-function 'insert-records)))
>    (defun insert-records (&rest args)
>      (let ((db (db)))
>        (prog1
>            (apply old-insert-records :database db args)
>          (disconnect :database db)))))
>
>
>
> --
> Yours Sincerely,
> Victor Kryukov
> _______________________________________________
> tbnl-devel site list
> tbnl-devel at common-lisp.net
> http://common-lisp.net/mailman/listinfo/tbnl-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.common-lisp.net/pipermail/tbnl-devel/attachments/20070415/9a570953/attachment.html>


More information about the Tbnl-devel mailing list