[plt-scheme] dynamic-wind & kill-thread
Well, it is the case that if you're using non-kill-safe- code (as it
sounds like spqsql is), then you cannot kill those threads.
You might be able to build a kill-safe wrapper for that code, however.
That is, put all of the code that queries the database into a single
thread and then communicate with that thread in a kill-safe manner
(much like the way the manager thread manages the queue in our kill
safe paper).
Robby
On Tue, Apr 21, 2009 at 12:42 PM, YC <yinso.chen at gmail.com> wrote:
>
> On Tue, Apr 21, 2009 at 3:42 AM, Robby Findler <robby at eecs.northwestern.edu>
> wrote:
>>
>> > what happens when a thread is killed in the middle of executing a
>> > dynamic-wind block? Does the post-thunk get executed still?
>>
>> No, it doesn't.
>
> Thanks for the verification.
>
>> In general, one might have to rewrite the program to make it
>> kill-safe. That is, there is no way to just take code that
>> synchronizes in some arbitrary way and make it kill-safe. Perhaps if
>> you can say more about what the actual syncronization protocol is, we
>> can help you make it kill-safe.
>
> I try to verify the possibility first to ensure my bug report is not bogus
> :)
>
> The blocked code exists in planet package schematics spgsql.plt, in
> private/p3.ss & private/connection.ss. Inside - it uses a semaphore to lock
> the critical region. The function protocol3:new-exchange waits for the
> semaphore, and protocol3:end-exchange releases the semaphore.
>
> protocol3:end-exchange appears to be only called by base%:end-exchange in
> private/connection.ss, which appears to be only called in
> primitive-query-mixin:with-final-end-exchange, which generates a
> dynamic-wind block that calls the end-exchange in post-thunk.
>
> My threads eventually block on protocol3:new-exchange, which appears to be
> waiting for a semaphore that's never released (and if dynamic-wind is not
> kill-safe that it can explain the behavior).
>
> This behavior is intermittent and hard to reproduce, but definitely there
> (as once it happens my app does nothing). Without Matthew's stack tracing
> approach I could not find out where it was blocking and how.
>
> Below is the code snippet from the two files.
>
> ;; private/p3.ss
> ;; protocol3:new-exchange : protocol3 -> stream
> (define (protocol3:new-exchange protocol)
> (semaphore-wait (protocol3-ownerlock protocol))
> ...)
> ;; protocol3:end-exchange : protocol3 -> void
> (define (protocol3:end-exchange protocol)
> (semaphore-post (protocol3-ownerlock protocol)))
>
> ;; private/connection.ss
> ;; base%
> (define base%
> (class* object% (base<%>)
> ...
> ;; new-exchange : -> stream
> (define/public-final (new-exchange)
> (unless protocol
> (raise-user-error 'connection<%> "not connected"))
> (protocol3:new-exchange protocol))
>
> ;; end-exchange : -> void
> (define/public-final (end-exchange)
> (unless protocol
> (raise-user-error 'connection<%> "not connected"))
> (protocol3:end-exchange protocol))
> ...))
> (define primitive-query-mixin
> (mixin (base<%>) (primitive-query<%>)
> ...
> (define-syntax with-final-end-exchange
> (syntax-rules ()
> [(with-final-end-exchange . b)
> (dynamic-wind
> void
> (lambda () . b)
> (lambda () (end-exchange)))]))
> ...))
>
>