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@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@common-lisp.net
http://common-lisp.net/mailman/listinfo/tbnl-devel