Version 0 of AtExit handlers

Updated 2002-08-30 12:46:15

AtExit handlers.

A common problem I had was that during an application I was setting up things like pipes (in the filesystem), add tons of temporary data, etc. I was then faced with the junk the program left after ending, so I was thinking of how to solve this, and was reminded of the atexit - C function.

So I wrote the following (it's quite short, that's why I include it here)

 rename exit __shock
 namespace eval ::AtExit {
        variable outchann
        namespace export outchan print
        proc outchan { {chan stderr} } {
                variable outchann
                if {[info exists outchann]&&
                    ($outchann != "stderr" && $outchann != "stdout")} {
                        close $outchann
                }
                set outchann $chan
        }
        proc noOutput { } {
                variable outchann
                if {[info exists outchann]&&
                    ($outchann != "stderr" && $outchann != "stdout")} {
                        flush $outchann
                        close $outchann
                }
                unset outchann
        }
        proc print { string } {
                variable outchann
                if {[info exists outchann]} {
                        puts $outchann $string
                }
        }
 }

 proc exit { {status 0}} {
        if {[info exists ::debugging] && $::debugging} {
                ::AtExit::outchan [open exit.log {WRONLY CREAT TRUNC}]
        }
        foreach proc [info procs AtExit_*] {
                if {![llength [info args $proc]]} {
                        ::AtExit::print "AtExit is calling finalizer <$proc>"
                        uplevel #0 $proc
                } else {
                        ::AtExit::print "AtExit found finalizer <$proc> to need arguments! Ignoring..."
                }
        }
        # This is no AtExit handler because it needs to
        # be called as absolutely last thing.
        if {[info exists ::AtExit::outchann] && 
            ($::AtExit::outchann != "stderr" && $::AtExit::outchann != "stdout")} {
                puts $::AtExit::outchann "Done handling exit handlers, closing stream and exitting."
                close $::AtExit::outchann
        }
        # bye bye
        __shock $status
 }
 package provide AtExit 0.1

This way you write some AtExit_* functions which expect no arguments, and which are called once you call exit. If you want to exit without calling those handlers, you can always __`shock` your program.

Another thing which comes handy, is to install a handler for your window if you use tk:

 wm protocol . WM_DELETE_WINDOW exit

This way even if you kill your application with the help of the windowmanager, exit will be called, and thus your exit-handlers will be called, too.

Hope this helps someone to resolve the issues I had.

Greetings, Martin Weber