Vahagn
Vahagn

Reputation: 4850

TCL hangs when trying to close TCL pipe

When launching tclsh and typing this:

close [open "|tclsh" w]

it works fine.

But, when in ~/.tclshrc you have package require Tk, the same line makes tclsh to HANG!

The same issue is with all GUI packages like Tk, Itk, Img, Iwidgets, however with not GUI packages like Itcl, it worsk fine.

How can I fix this issue? The point is to make tclsh not to hang, when typing close [open "|tclsh" w] with package require Tk in ~/.tclshrc.

The same issue is with wish. close [open "|wish" w] makes wish to HANG (with an empty ~/.wishrc file)!

I got this issue on both 32 and 64 bit CentOS. I have the following versions of packages: tcl-8.5.8, tk-8.5.8, img-1.3, itcl-3.4.b1, itk-3.3, iwidgets-4.0.1.

Upvotes: 1

Views: 1334

Answers (2)

Donal Fellows
Donal Fellows

Reputation: 137787

Tcl applications mostly exit when they have finished their script, whether or not it is provided interactively. However the Tk package changes things around so that when the end of the script is reached, it instead goes into a loop handling events. If you're relying on an end-of-file causing things to exit, that's going to look a lot like a hang, but really it's just waiting properly for the GUI app to finish (so it can report the exit status of the subprocess).

The fix is to make a channel-readable event handler for stdin in the subprocess. There's a few ways to do this in detail, but here's a simple one that can go at the end of the bulk of code that you normally send:

proc ReadFromStdin {} {
    if {[gets stdin line] >= 0} {
        uplevel "#0" $line
    } elseif {[eof stdin]} {
        exit
    } else {
        # Partial read; try later when rest of data available
    }
}
fileevent stdin readable ReadFromStdin

This assumes that each line is a full executable command; that might not be true, of course, but writing the code to use info complete to compose lines is less clear and possibly unnecessary here. (You know what you're actually sending better than I…)

Upvotes: 2

RHSeeger
RHSeeger

Reputation: 16282

My thought would be that it's waiting for wish to finish running, as per the man page:

If channelId is a blocking channel for a command pipeline then close waits for the child processes to complete.

Since wish enters an infinite loop (the event loop) and never exits, the close command will hang. Along the same lines, [package require Tk] (I believe) starts the event loop, so will cause the same behavior.

I'll admit though that it's loading .tclshrc at all, since

If there exists a file .tclshrc (or tclshrc.tcl on the Windows platforms) in the home directory of the user, interactive tclsh evaluates the file as a Tcl script just before reading the first command from standard input.

It seems odd to me that [open "|tclsh" w] winds up in an interactive shell.

As a side note, [pacakge require Tk] seems like a really strange thing to do in .tclshrc. In theory, you won't always want Tk (the window and event loop) when running Tcl (ie, command line only apps)... and, when you do want it, you know you do. To each their own, I suppose, it just seems odd to me.

Upvotes: 1

Related Questions