When an evaluation fails or is interrupted, it may be convenient to automatically kill tasks created during the evaluation. One use for this might be for debugging a set of long-running tasks. Here is a solution using alexandria’s unwind-protect-case
.
(defpackage :example (:use :cl :lparallel :alexandria))
(in-package :example)
(defun call-with-kill-on-abort (fn task-category)
(let ((*task-category* task-category))
(unwind-protect-case ()
(funcall fn)
(:abort (kill-tasks task-category)))))
(defmacro with-kill-on-abort ((&key (task-category '*task-category*))
&body body)
`(call-with-kill-on-abort (lambda () ,@body) ,task-category))
(defun foo ()
(with-kill-on-abort (:task-category 'foo-stuff)
(pmap nil #'sleep '(9999 9999))))
Example run in SLIME:
CL-USER> (example::foo) ; ... then hit C-c-c
WARNING: lparallel: Replacing lost or dead worker.
WARNING: lparallel: Replacing lost or dead worker.
; Evaluation aborted on NIL.
As always, worker threads are regenerated after being killed.