timeouttcluser-feedback

timeout handler in simple Tcl scripts?


I have a number of scripts that load a library of utility functions which can take a variable time to initialise.

I'd prefer not to print an "initialising XXXX" message each time I invoke one of those scripts, but would love to have some "This is taking a bit longer" message when appropriate. The general structure of those scripts is

package require theLibrary
# prepare stuff
if {[catch {theLibraryInit x y z} result]} {
    puts stderr $::errorInfo
    puts "Initialisation failed ($result)"
    exit -1
}
# do stuff

According to Stop a TCL script from freezing while processing a command, I should be able to use the Tcl after command, but even with after 1 [list patienceWarning] I'm not getting any output.

I suppose I'd have to put an eventloop around my scripts' payload, but what would be the most straightforward way to do that?


Solution

  • The easiest way is likely to be to run the wait and message print in another thread, and to send a message to that thread to cancel things there if the main thread finishes its work in time.


    The problem with using after in the main thread to do this is that Tcl only services events including timer events when the event loop is running. If you are busy (and aren't calling update periodically) then the timeout won't get responded to until much later. While it is quite possible to make that work, it's messy and prone to problems (due to the possibility of reentrant event handling).

    Using a separate thread that just does the (cancellable) wait is so much easier. Tcl's threads are true system threads, so the busy main thread won't block the message printing.

    You can likely reuse that thread for many such waits; timeout waits are generally very cheap.