"Emilio Lopes" <eclig@gmx.net> writes:
> I have here some objects whose creation involves starting external
> processes. I would like these processes to be properly shut down when
> the corresponding objects are garbage-collected.
>
> So I tried using `add-finalizer!' for this purpose and couldn't get it
> to work. Here is an example:
>
> Welcome to scsh 0.6.7 (RC 1)
> Type ,? for help.
> > ,open define-record-types primitives
> > (define-record-type foo :foo
> (really-make-foo x)
> (x foo:x))
> > (define bar #f)
> > (define (make-foo x)
> (let ((new-foo (really-make-foo x)))
> (add-finalizer! new-foo
> (lambda (obj)
> (set! bar 1)))
> new-foo))
> > (make-foo 43)
> '#{Foo}
> > ,collect
> Before: 10608482 words free in semispace
> After: 10673414 words free in semispace
> > bar
> #f
> >
>
> I was expecting `bar' to be 1 at this point. The same example works
> as expected under Scheme 48 1.3.
>
> Isn't this the way it's supposed to work?
The problem is that NEW-FOO is part of the closure that you pass as
the finializer and thus can never be GCed (since the finalizer closure
is always alive, NEW-FOO is always alive).
You therefore need to re-write your code as follows:
Welcome to scsh 0.6.7 (R6RS)
Type ,? for help.
> ,open define-record-types primitives
> (define-record-type foo :foo
(really-make-foo x)
(x foo:x))
> (define bar #f)
> (define (finalize-foo! a-foo) (set! bar 1))
> (define (make-foo x)
(let ((new-foo (really-make-foo x)))
(add-finalizer! new-foo finalize-foo!)
new-foo))
> (make-foo 43)
'#{Foo}
> ,collect
Before: 1204331 words free in semispace
After: 1294606 words free in semispace
> bar
#f [1]
> ,collect
Before: 1287285 words free in semispace
After: 1295642 words free in semispace
> bar
1
Your code works as expected in S48 1.3 because S48 1.3 uses a
different environment representation where only needed variables are
contained in a closure's environment.
Footnotes:
[1] the finalizer did not run here because the focus object (##) is bound to
{Foo}
--
Martin
|