[plt-scheme] dynamic-wind & kill-thread

From: Robby Findler (robby at eecs.northwestern.edu)
Date: Tue Apr 21 15:09:14 EDT 2009

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)))]))
>      ...))
>
>


Posted on the users mailing list.