Executes code with a "debugger wrapper" which is called only if the debugger is invoked during the execution.
The macro with-debugger-wrapper
executes forms in body with the function wrapper bound as a "debugger wrapper". This debugger wrapper takes effect only if the code in body tries to invoke the debugger (by a call to invoke-debugger
), typically indirectly as a result of an error. Instead of entering the debugger, the debugger wrapper is called with two arguments: a function to call to enter the debugger, and the condition. The wrapper can do whatever is needed. If it wants to enter the debugger, it does it by calling its first argument with the second argument:
(funcall function condition)
Suppose that you run many processes in parallel with the same code. If the code is broken then every process will get an error. This example shows how a debugger wrapper can be used to keep a lock around entry to the debugger, so that the processes enter the debugger one by one. It contains firstly the "application code", then the debugger wrapper, and lastly forms which execute the application with or without the debugger wrapper.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;; application code ;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(in-package "CL-USER")
(defglobal-parameter *a* 0)
(defun foo (index cons)
(sys:atomic-push (* index *a*) (cdr cons)))
;; This gets the process function so we can pass
;; the wrapper function instead.
(defun my-run-processes (do-error &optional
(process-function 'foo))
(setq *a* (if do-error :do-error 7))
(let ((cons (cons nil nil)))
(dotimes (x 10)
(mp:process-run-function
(format nil "My test process ~d" x)
()
process-function
x cons))
(sleep 0.2)
(print (cdr cons))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;; debugger wrapper ;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defglobal-parameter *my-debugger-lock*
(mp:make-lock :name "Debugger Lock"))
(defun my-debugger-wrapper (func condition)
(mp:with-lock (*my-debugger-lock*)
(funcall func condition)))
(defun foo-wrapper (index cons)
(dbg:with-debugger-wrapper 'my-debugger-wrapper
(foo index cons)))
;; Running the application without the wrapper fills
;; your screen with notifiers
(my-run-processes t)
;; Running with the wrapper raises the notifiers one by
;; one. You can use the Process Browser kill them all.
(my-run-processes t 'foo-wrapper)
LispWorks User Guide and Reference Manual - 20 Sep 2017