Summary
dynamic wind in its own thread
Metadata
- Id: d33f2c22a1e1beb810be281e4ecf3d031418a112
- Trac id: 1127
- Type: defect
- Reporter: kristianlm
- Owner:
- Cc:
- Status: closed
- Component: unknown
- Estimated difficulty:
- Resolution: invalid
- Priority: major
- Milestone: someday
- Version: 4.9.x
- Changetime: 2014-05-27 16:01:38 UTC
- Created: 2014-05-22 16:37:43 UTC
- Keywords:
Description
I'm running this code in 4.9.0rc1:
(define (trick)
(dynamic-wind (lambda () (print "before"))
(lambda () (error 'foo))
(lambda () (print "after"))))
- ; calls before and after, no surprises
(trick)
- ; calls before only - why?
(thread-start! (lambda () (trick)))
- ; calls before and after, no surprises
(thread-start!
(lambda () (handle-exceptions e (raise e) (trick))))
- ;; It outputs
before
Error: foo
Call history: <syntax> (trick) <eval> (trick) <eval> [[trick]|] (dynamic-wind (lambda () (print "before")) (lambda () (error (quote foo))) (lambda () (print "after"... <eval> [[trick]|] (print "before") <eval> [[trick]|] (error (quote foo)) <--
after #<thread: thread22> before
Warning (#<thread: thread22>): in thread: foo
Call history: <eval> (trick) <eval> [[trick]|] (dynamic-wind (lambda () (print "before")) (lambda () (error (quote foo))) (lambda () (print "after"... <eval> [[trick]|] (print "before") <eval> [[trick]|] (error (quote foo)) <--
- ; I expect to see "after" printed on the second run too
Changes and comments
[2014-05-22 17:15:16 UTC] kristianlm wrote:
Meanwhile, here's a workaround:
(use srfi-18 test)
;; define original@thread-start! once
(define original#thread-start!
(handle-exceptions e thread-start!
original#thread-start!))
(define (##dbg#thread-thunk thread)
(##sys#slot thread 1))
(define (thread-start! thread)
;; original thunk
(define original-thunk
(if (thread? thread)
(##dbg#thread-thunk thread)
thread))
;; simply wrap original thunk inside a handle-exceptions with
;; re-raises any errors seem to do the trick
(define (thunk)
(handle-exceptions e (raise e)
(original-thunk)))
(original#thread-start!
(if (thread? thread)
(make-thread thunk (thread-name thread))
(make-thread thunk))))
(test-group
"dynamic-wind.workaround"
(define ran? #f)
(define (trick)
(dynamic-wind (lambda () (void))
(lambda () (error 'x))
(lambda () (set! ran? #t))))
;; throw away warnings
(parameterize ((current-error-port (open-output-string)))
(test-error
(thread-join!
(thread-start!
(lambda () (trick))))))
(test #t ran?))
This test-group passes, but fails if you don't redefine thread-start!.
[2014-05-22 22:18:12 UTC] ckeen wrote:
The manual states: (http://api.call-cc.org/doc/srfi-18)
When an error is triggered inside the execution context of a thread, the default exception-handler will simply terminate the thread and store the error condition for later use). Pending dynamic-wind thunks will not be invoked. Use a custom exception handler for the thread in that case.
To me that's exactly what happens here? Or am I missing something more subtle?
[2014-05-27 16:01:38 UTC] kristianlm changed status from new to closed
[2014-05-27 16:01:38 UTC] kristianlm set resolution to invalid
[2014-05-27 16:01:38 UTC] kristianlm wrote:
Of course, I was reading the part on "dynamic-wind" thoroughly without finding anything about this. But this makes very much sense. We will wrap our thread-thunks in our own exception-handlers (which I've actually tested works).
So the behavior is indeed like expected when you actually read the whole srfi-18 manual.
Thanks CKeen!