cl-cookbook
cl-cookbook copied to clipboard
Elaborate on why BT:DESTROY-THREAD is a bad idea
Augment https://lispcookbook.github.io/cl-cookbook/process.html#joining-on-a-thread-destroying-a-thread with the following:
Using bt:destroy-thread is a bad idea in the general case. Threads should instead finish on their own to do all the cleanup that they might need to do - one should never use bt:destroy-thread in production code. Destroying threads from outside is only feasible as a measure of last resort, as it can and eventually will leave the application in an unknown state.
It is better to bt:interrupt-thread #'break and select the bottommost abort restart in order to let the thread unwind completely. A programmatic version of this would be:
(defun abort-thread (thread)
(flet ((thunk ()
;; We must call COMPUTE-RESTARTS in the dynamic context of the thread
;; that we want to abort, not of the thread that performs the
;; interruption.
(let* ((restarts (compute-restarts))
;; We assume that the last ABORT restart causes the whole
;; thread to unwind and exit gracefully.
(abort-restarts (remove-if-not (alexandria:curry #'eq 'abort)
restarts :key #'restart-name))
(abort-thread-restart (alexandria:lastcar abort-restarts)))
(invoke-restart abort-thread-restart))))
;; Interrupt the target thread with our thunk and force it to invoke the
;; ABORT restart, therefore initiating the unwind.
(bt:interrupt-thread thread thunk)))
TODO: check if this works on implementations other than SBCL.