|
From: Ryan C. <ry...@cc...> - 2007-08-16 21:52:14
|
On Aug 16, 2007, at 3:48 PM, Eric Hanchrow wrote:
> Here's a problem which I've already solved, but I'm not in love with
> the solution, and am wondering if there's a better way.
>
> I have some functions that create threads, and sometimes those threads
> raise uncaught exceptions. And sometimes, alas, my tests don't notice
> (because the dead thread didn't directly contribute to the result my
> tests are looking for). And sometimes I don't notice the exception,
> since its only evidence is a few lines of output, which tend to get
> lost amongst all the other output.
>
> So I'd like a way for the tests to fail when a child thread raises an
> uncaught exception. Attached is the way I've found to do it, but it
> just seems clunky. Can someone suggest a better way?
> <thread-trouble.ss>
I would combine the check of the result with the check that no child
thread threw an exception into one test, because they are part of the
same overall computation. As a rule, I try to keep my test cases
totally independent. In your example, the execution of the second test
depends on the state left by the first test.
Here's a procedure that might help. It's similar to your code, but it's
designed to be used locally within a test-case. It also checks that any
auxiliary threads are no longer running when the main computation
finishes. You may have to customize it to get what you want.
;; check-threads : (-> any) -> any
;; Runs thunk; raises error if any subthreads created by thunk raise
;; errors, or if a subthread outlives thunk's computation.
(define (check-threads thunk)
(let* ([main-cust (current-custodian)]
[sub-cust (make-custodian main-cust)]
[sub-exns null]
[old-uncaught-exception-handler (uncaught-exception-handler)])
(parameterize ((current-custodian sub-cust)
(uncaught-exception-handler
(lambda (exn)
(set! sub-exns (cons exn sub-exns))
(old-uncaught-exception-handler exn))))
(let ([result (thunk)])
;; Check that sub-custodian has no living threads.
(let ([threads-still-going?
(ormap thread-running?
(filter thread? (custodian-managed-list sub-cust
main-cust)))])
(when (pair? sub-exns)
(error 'nice-threads "child thread raised exception"))
(when threads-still-going?
(error 'nice-threads "child thread left still running"))
result)))))
;; error: child thread left still running
(check-threads
(lambda ()
(thread (lambda () (sleep 1) 17))
1))
;; error: child thread raised exception
(check-threads
(lambda ()
(thread (lambda () (error "whoops")))
1))
;; okay
(check-threads
(lambda ()
(let ([t (thread (lambda () (sleep 1) 17))])
(thread-wait t)
18)))
Ryan
> --
> A bad analogy is like a leaky screwdriver.
> -- Richard Braakman
> -----------------------------------------------------------------------
> --
> This SF.net email is sponsored by: Splunk Inc.
> Still grepping through log files to find problems? Stop.
> Now Search log events and configuration files using AJAX and a browser.
> Download your FREE copy of Splunk now >>
> http://get.splunk.com/_______________________________________________
> Schematics-development mailing list
> Sch...@li...
> https://lists.sourceforge.net/lists/listinfo/schematics-development
|