Opened 14 years ago
Closed 14 years ago
#446 closed defect (fixed)
Finalizers for top level bindings don't get executed upon program exit
Reported by: | Moritz Heidkamp | Owned by: | |
---|---|---|---|
Priority: | minor | Milestone: | |
Component: | core libraries | Version: | 4.6.x |
Keywords: | Cc: | ||
Estimated difficulty: |
Description
The following program does never print "finalized x", neither when interpreted nor compiled:
(define x (list 1)) (set-finalizer! x (lambda (x) (print "finalized x")))
Appending (set! x #f)
, it does.
Change History (9)
comment:1 Changed 14 years ago by
comment:2 follow-up: 3 Changed 14 years ago by
Finalizers are not called on program exit. Also, in the interpreter, results (including the result of set-finalizer!
, which is the finalized object) are stored in the REPL history and so never freed.
comment:3 follow-up: 4 Changed 14 years ago by
Replying to felix:
Finalizers are not called on program exit.
Is there a good reason for this or is it just not implemented? I wonder since ##sys#cleanup-before-exit
in library.scm calls ##sys#force-finalizers
and is registered as an exit-handler. Can you clarify this?
Also, in the interpreter, results (including the result of
set-finalizer!
, which is the finalized object) are stored in the REPL history and so never freed.
Yep, when I said "interpreter" I meant a script executed with csi -s
, not the REPL.
comment:4 Changed 14 years ago by
Replying to syn:
Replying to felix:
Finalizers are not called on program exit.
Is there a good reason for this or is it just not implemented? I wonder since
##sys#cleanup-before-exit
in library.scm calls##sys#force-finalizers
and is registered as an exit-handler. Can you clarify this?
Forcing finalizers will only run those that have become garbage. The fact that a process terminates does not mean all toplevel variables become garbage, which many language implementations handle that way.
I have documented this. Is this acceptable for you?
comment:5 follow-up: 7 Changed 14 years ago by
Okay, that makes sense then, thanks! I assumed indeed that all data is considered garbage at program exit. I think this implies that programs relying on finalizers to clean up (possibly remote) state should additionally define an exit handler to be on the safe side then. Just out of curiosity: Would changing the behavior to consider all remaining top level bindings at program exit garbage and run their finalizers mean a big change and would it potentially break a lot of code? Otherwise I'd suggest changing to this behavior and maybe add a command line switch to disable it.
comment:6 follow-up: 8 Changed 14 years ago by
I just compiled the current experimental and the let
example I mentioned in the first comment here still does not work in the interpreter even when adding a (gc #t) at the end. Compiled it still works as before. Since x is not bound at the top level here, souldn't it indeed be finalized in both cases?
comment:7 Changed 14 years ago by
Replying to syn:
Okay, that makes sense then, thanks! I assumed indeed that all data is considered garbage at program exit. I think this implies that programs relying on finalizers to clean up (possibly remote) state should additionally define an exit handler to be on the safe side then.
Yes, that would be possible.
Just out of curiosity: Would changing the behavior to consider all remaining top level bindings at program exit garbage and run their finalizers mean a big change and would it potentially break a lot of code?
It would be a big change since all sorts of crap would start running once the program terminates. Finalizers are icky. Finalizers give you the non-determinism of threads but without the synchronization and should be avoided unless absolutely necessary (strictly speaking, they should run in a separate threads).
Otherwise I'd suggest changing to this behavior and maybe add a command line switch to disable it.
I probably sound like an asshole, but that is also a bad idea. :-) Making behaviour like this depending on command-line- or configuration options just make maintenance unnecessary hard. I suggest you give an example that explains the motivation for what you seem to request.
comment:8 Changed 14 years ago by
Component: | unknown → core libraries |
---|---|
Milestone: | 4.7.0 |
Priority: | major → minor |
Replying to syn:
I just compiled the current experimental and the
let
example I mentioned in the first comment here still does not work in the interpreter even when adding a (gc #t) at the end. Compiled it still works as before. Since x is not bound at the top level here, souldn't it indeed be finalized in both cases?
The interpreter uses a simple linked-list environment-representation, and I assume that the finalizer-closure reaches back into the outer environment containing the datum. Something like this should work:
(define (finalized x) ...) (begin (set-finalizer! x finalized) #f)
comment:9 Changed 14 years ago by
Resolution: | → fixed |
---|---|
Status: | new → closed |
Apparently this is not only true for top level bindings. This program also doesn't print anything when interpreted (but in contrast, it does when compiled!):