Version 15 of Dumping interpreter state

Updated 2004-10-10 23:27:22

Richard Suchenwirth 2002-10-30 - A need that comes up every now and then (see Persistent Tcl and Tk applications) is to dump the state of an interpreter to a file, so the application can later be restored (by sourceing the resulting file) to a state with the same settings. Here's a simple generic test for serializing global variables (scalar or array), interpreter aliases, and procedures, taking care to skip env and Tcl internals. Feel free to improve on this ;-)

As mentioned on comp.lang.tcl, this is not a complete state dump; just a reasonable facimile. Things like open file descriptors, sockets, daemons started, etc. are particularly difficult to handle, as are various extension specific items (like Tk widgets, Snack components, and many other such entities).

Packages are sort of taken care of in the code below; namespaces would require traversal of the namespace tree, repeating variable and proc dumping.

AK: Note that tkcon contains dump routines as well, for namespaces too. - RS: Sure - it's just the little mental challenge of building something "with your bare hands"... more fun for a short break than reading yet more documentation or source code ;-)


 proc interp'dump {} {
     set res "\# interpreter status dump\n"
     catch {package require "a non-existing one"}
     foreach package [lsort [package names]] {
         if {![catch {package present $package} version]} {
             append res "package require $package $version" \n
         }
     }
     foreach i [lsort [info globals]] {
         if {$i == "env"} continue  ;# don't dump environment..
         if {[string match tcl_* $i]} continue ;# ..or Tcl system vars
         if {[string match auto_index $i]} continue ;# ..or Tcl system vars
         if {[array exists ::$i]} {
             append res [list array set $i [array get ::$i]]\n
         } else {
             append res [list set $i [set ::$i]]\n
         }
     }
     foreach proc [lsort [info procs]] {
         if {[string match auto_* $proc] || $proc == "unknown"} {
             continue ;# prevents most of the init.tcl procs from dumping
         }
         if {[string match pkg_* $proc]} continue ;# ..or Tcl system vars
         if {[string match tcl* $proc]} continue ;# ..or Tcl system vars
         append res "proc [list $proc] {"
         set space ""
         foreach i [info args $proc] {
             if [info default $proc $i value] {
                 append res "$space{$i [list $value]}"
             } else {
                 append res "$space$i"
             }
             set space " "
         }
         append res "} {[info body $proc]}\n"
     }
     foreach alias [lsort [interp aliases {}]] {
         append res "interp alias {} $alias {} [interp alias {} $alias]\n"
     }
     set res
 }
 if {[file tail [info script]] == [file tail $argv0]} {
    # prepare some playing material
    set scalar hello
    array set arry {foo 1 bar 2 grill 3}
    proc foo {bar} {puts grill-$bar}
    interp alias {} print {} puts stdout
    puts [interp'dump]
 }

[L1 ][L2 ][L3 ][L4 ][L5 ][L6 ][L7 ][L8 ][L9 ][L10 ][L11 ][L12 ][L13 ][L14 ][L15 ][L16 ][L17 ][L18 ][L19 ][L20 ][L21 ][L22 ][L23 ][L24 ][L25 ][L26 ][L27 ][L28 ][L29 ][L30 ][L31 ][L32 ][L33 ][L34 ][L35 ][L36 ][L37 ][L38 ][L39 ][L40 ][L41 ][L42 ][L43 ][L44 ][L45 ][L46 ][L47 ][L48 ][L49 ][L50 ][L51 ][L52 ][L53 ][L54 ][L55 ][L56 ][L57 ][L58 ][L59 ][L60 ][L61 ][L62 ][L63 ][L64 ][L65 ][L66 ][L67 ][L68 ][L69 ][L70 ][L71 ][L72 ][L73 ][L74 ][L75 ][L76 ][L77 ][L78 ][L79 ][L80 ][L81 ][L82 ][L83 ][L84 ][L85 ][L86 ][L87 ][L88 ][L89 ][L90 ][L91 ][L92 ][L93 ][L94 ][L95 ][L96 ][L97 ][L98 ][L99 ][L100 ][L101 ][L102 ][L103 ][L104 ][L105 ][L106 ][L107 ][L108 ][L109 ][L110 ][L111 ][L112 ][L113 ][L114 ][L115 ][L116 ][L117 ][L118 ][L119 ][L120 ][L121 ][L122 ][L123 ][L124 ][L125 ][L126 ][L127 ][L128 ][L129 ][L130 ][L131 ][L132 ][L133 ][L134 ][L135 ][L136 ][L137 ][L138 ][L139 ][L140 ][L141 ][L142 ][L143 ][L144 ][L145 ][L146 ][L147 ][L148 ][L149 ][L150 ][L151 ][L152 ][L153 ][L154 ][L155 ][L156 ][L157 ][L158 ][L159 ][L160 ][L161 ][L162 ][L163 ][L164 ][L165 ][L166 ][L167 ][L168 ][L169 ][L170 ][L171 ][L172 ][L173 ][L174 ][L175 ][L176 ][L177 ][L178 ][L179 ][L180 ][L181 ][L182 ][L183 ][L184 ][L185 ][L186 ][L187 ][L188 ][L189 ][L190 ][L191 ][L192 ][L193 ][L194 ][L195 ][L196 ][L197 ][L198 ][L199 ][L200 ][L201 ][L202 ][L203 ][L204 ][L205 ][L206 ][L207 ][L208 ][L209 ][L210 ][L211 ][L212 ][L213 ][L214 ][L215 ][L216 ][L217 ][L218 ][L219 ][L220 ][L221 ][L222 ][L223 ][L224 ][L225 ][L226 ][L227 ][L228 ][L229 ][L230 ][L231 ][L232 ][L233 ][L234 ][L235 ][L236 ][L237 ][L238 ][L239 ][L240 ][L241 ][L242 ][L243 ][L244 ][L245 ][L246 ][L247 ][L248 ][L249 ][L250 ][L251 ][L252 ][L253 ][L254 ][L255 ][L256 ][L257 ][L258 ][L259 ][L260 ][L261 ][L262 ][L263 ][L264 ][L265 ][L266 ][L267 ][L268 ][L269 ][L270 ][L271 ][L272 ][L273 ][L274 ][L275 ][L276 ][L277 ][L278 ][L279 ][L280 ][L281 ][L282 ][L283 ][L284 ][L285 ][L286 ][L287 ][L288 ][L289 ][L290 ][L291 ][L292 ][L293 ][L294 ][L295 ][L296 ][L297 ][L298 ][L299 ][L300 ][L301 ][L302 ][L303 ][L304 ][L305 ][L306 ][L307 ][L308 ][L309 ][L310 ][L311 ][L312 ][L313 ][L314 ][L315 ][L316 ][L317 ][L318 ][L319 ][L320 ][L321 ][L322 ][L323 ][L324 ][L325 ][L326 ][L327 ][L328 ][L329 ][L330 ][L331 ][L332 ][L333 ][L334 ][L335 ][L336 ][L337 ][L338 ][L339 ][L340 ][L341 ][L342 ][L343 ][L344 ][L345 ][L346 ][L347 ][L348 ][L349 ][L350 ][L351 ][L352 ][L353 ][L354 ][L355 ][L356 ][L357 ][L358 ][L359 ][L360 ][L361 ][L362 ][L363 ][L364 ][L365 ][L366 ][L367 ][L368 ][L369 ][L370 ][L371 ][L372 ][L373 ][L374 ][L375 ][L376 ][L377 ][L378 ][L379 ][L380 ][L381 ][L382 ][L383 ][L384 ][L385 ][L386 ][L387 ][L388 ][L389 ][L390 ][L391 ][L392 ][L393 ][L394 ][L395 ][L396 ][L397 ][L398 ][L399 ][L400 ][L401 ][L402 ][L403 ][L404 ][L405 ][L406 ][L407 ][L408 ][L409 ][L410 ][L411 ][L412 ][L413 ][L414 ][L415 ][L416 ][L417 ][L418 ][L419 ][L420 ][L421 ][L422 ][L423 ][L424 ][L425 ][L426 ][L427 ][L428 ][L429 ][L430 ][L431 ][L432 ][L433 ][L434 ][L435 ][L436 ][L437 ][L438 ][L439 ][L440 ][L441 ][L442 ][L443 ][L444 ][L445 ][L446 ][L447 ][L448 ][L449 ][L450 ][L451 ][L452 ][L453 ][L454 ][L455 ][L456 ][L457 ][L458 ]


Smalltalk provides a mechanism for dumping state into a so called image. Smalltalk images contains all global variables, classes und compiled methods. The image is the internal (byte-coded) state of interpreter.

The example on this page trys instead to create one big Tcl script to reset variables after an application begins. (What is this new created procs, tcl is dynamic).

I would think more about dumping the interpreter's internal state (binary) and then loading it. Loading byte code should be much faster than compiling the sources anew. the Tcl interpreter could realize such functionality if it could serialize Tcl_Obj (internal Tcl) but I think the current Tcl interpreter does not allow this (or perhaps no one has thought about it). The biggest problem are the Tcl extensions. All Tcl extensions should then also serialize their states. In principle if in tcl everything were a string it would be easy. In fact, often these strings are names of handles (file handle, tk windows handle, etc.). This is not so easy to differenciate what to dump and what needs to be recreated - or for that matter, how to recreate it.

I think TclPro has the ability to save byte-coded procedures, but I do not know how it could be used for such dumping.


Recently Karl Lehenbauer mentioned that TclX has a proc called showproc which extracts named procs or all procs. He also mentioned that it would be neat for a Tcl hacker with some spare time to create a new interp clone command that creates a new intepreter, copying in all of the original's procs, variables, open file descriptors, namespaces, packages, etc. This if done quickly, could be used as something lighter weight than fork.


XOTcl has a class called Serializer that can dump objects, classes and all the whole workspace (in the right order) into a string which can be used to recreate at some later time [L459 ]. This is used to generate the blueprint of the interpreter state in AOLserver or e.g. for object migration between threads.


Arts and crafts of Tcl-Tk programming