[racket-dev] Should `register-finalizer` unwrap impersonators?

From: Sam Tobin-Hochstadt (samth at cs.indiana.edu)
Date: Sat Aug 16 10:46:24 EDT 2014

That's clearly the right solution for this particular bug, but it does
seem like there's a more general problem here.

Sam

On Sat, Aug 16, 2014 at 10:40 AM, Robby Findler
<robby at eecs.northwestern.edu> wrote:
> Seems simplest to be to have typed racket know to trust register finalizer
> and thus avoid wrapping it with a contract.
>
> Robby
>
>
> On Saturday, August 16, 2014, Neil Toronto <neil.toronto at gmail.com> wrote:
>>
>> Short version: the contract system doesn't allow `register-finalizer` to
>> be used in Typed Racket.
>>
>> Long version: consider the following Typed Racket program, in which
>> instances of `os-resource-wrapper` represent an operating system resource
>> `os-resource`, which itself is just a counter. It attempts to register a
>> finalizer for allocated wrappers, which decrements the counter.
>>
>>
>> #lang typed/racket
>>
>> (require/typed
>>  ffi/unsafe
>>  [register-finalizer  (All (A) (-> A (-> A Any) Void))])
>>
>> (: os-resource Integer)
>> (define os-resource 0)
>>
>> (struct os-resource-wrapper ())
>>
>> (: alloc-os-resource (-> os-resource-wrapper))
>> (define (alloc-os-resource)
>>   (set! os-resource (add1 os-resource))
>>   (define w (os-resource-wrapper))
>>   (register-finalizer w (λ (w) (set! os-resource (sub1 os-resource))))
>>   w)
>>
>> (define w (alloc-os-resource))
>> (printf "os-resource = ~v~n" os-resource)
>> (collect-garbage)
>> (sleep 1)  ; give finalizers a chance to run
>> (printf "os-resource = ~v~n" os-resource)
>>
>>
>> I get this output:
>>
>>   os-resource = 1
>>   os-resource = 0
>>
>> The finalizer is being run while the program still has a pointer to the
>> wrapper object. I think it's because the wrapper object is being
>> impersonated when it's sent across the contract barrier, and the
>> *impersonator* is getting the finalizer. (Or it's a chaperone, or an
>> impostor, or a charlatan, or whatever. Let's go with impersonator.)
>>
>> In my specific case, the OS resources are OpenGL objects; e.g. vertex
>> object arrays. The call to `register-finalizer` *must* be in Typed Racket
>> code because the wrapper contains an (Instance GL-Context<%>), which can't
>> have a contract put on it, so it can't pass from untyped to typed code.
>>
>> Is there any reason for `register-finalizer` to behave this way? Does it
>> ever make sense to register a finalizer on an impersonator?
>>
>> Neil ⊥
>> _________________________
>>  Racket Developers list:
>>  http://lists.racket-lang.org/dev
>
>
> _________________________
>   Racket Developers list:
>   http://lists.racket-lang.org/dev
>


Posted on the dev mailing list.