Kill-safe cleanup of locally created threads

I'm interested in ensuring kill-safe cleanup of locally created threads in an arbitrary execution context. For instance, a user might run my code in a thread that is not managed by a custodian, which they then kill at an arbitrary time.

I've come up with a solution that seems to work, but is there a better way to accomplish the same thing?

(define (thread-add-finalizer t finalize)
  (thread (lambda () (thread-wait t) (finalize)))
  (void))

(define (make-a-mess)
  (let ((cust (make-custodian)))
    (thread-add-finalizer (current-thread) (lambda () (custodian-shutdown-all cust)))
    (parameterize ((current-custodian cust))
      (thread (lambda () (let loop () (displayln 'mess-1) (sleep 5) (loop))))
      (thread (lambda () (let loop () (displayln 'mess-2) (sleep 6) (loop)))))
    (let loop ()
      (displayln 'maintaining-mess)
      (sleep 7)
      (loop))))

(define mess (thread make-a-mess))
(sleep 20)
(kill-thread mess)
2 Likes

Given the lack of replies, I'll assume the answer is either negative or unclear.

So for future reference, I'll record one more improvement I noticed. The finalizer should be managed by the custodian it shuts down so that if we manually shut the custodian down ourselves, we also clean up the finalizer thread at the same time, to avoid accumulating obsolete finalizers.

(define (thread-add-finalizer t finalize)
  (thread (lambda () (thread-wait t) (finalize)))
  (void))

(define (make-a-mess)
  (let ((cust (make-custodian)))
    (parameterize ((current-custodian cust))
      ;; safer placement of finalizer
      (thread-add-finalizer (current-thread) (lambda () (custodian-shutdown-all cust)))
      (thread (lambda () (let loop () (displayln 'mess-1) (sleep 5) (loop))))
      (thread (lambda () (let loop () (displayln 'mess-2) (sleep 6) (loop)))))
    (let loop ()
      (displayln 'maintaining-mess)
      (sleep 7)
      ;; etc. we may eventually shutdown cust ourselves, and don't want the finalizer to leak.
      (loop))))

(define mess (thread make-a-mess))
(sleep 20)
(kill-thread mess)
2 Likes