尝试关闭TCL管道时TCL挂起

时间:2010-09-12 09:39:27

标签: user-interface tcl pipe

启动tclsh并输入:

close [open "|tclsh" w]

它工作正常。

但是,当~/.tclshrc中有package require Tk时,同一行会使tclsh变为HANG!

同样的问题是所有的GUI软件包,如Tk,Itk,Img,Iwidgets,但是如果没有像Itcl这样的GUI软件包,它就会很糟糕。

如何解决此问题?关键是在tclsh中使用close [open "|tclsh" w]键入package require Tk时,~/.tclshrc不要挂起。

同样的问题是wishclose [open "|wish" w]希望HANG(带有~/.wishrc个空文件)!

我在32位和64位CentOS上都遇到了这个问题。 我有以下版本的软件包:tcl-8.5.8,tk-8.5.8,img-1.3,itcl-3.4.b1,itk-3.3,iwidgets-4.0.1。

2 个答案:

答案 0 :(得分:2)

Tcl应用程序主要在完成脚本时退出,无论是否以交互方式提供。然而,Tk包改变了一些东西,以便在到达脚本结束时,它转而进入循环处理事件。如果你依赖于文件结尾导致事情退出,这看起来很像挂起,但实际上它只是等待GUI应用程序完成(因此它可以报告子进程的退出状态) )。

修复方法是在子进程中为stdin创建一个通道可读的事件处理程序。有几种方法可以详细地做到这一点,但这里有一个简单的方法可以放在你通常发送的大量代码的末尾:

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

这假定每一行都是完整的可执行命令;当然,这可能不是真的,但编写使用info complete来组成行的代码不太清楚,在这里可能是不必要的。 (你知道你实际发送的东西比我更好......)

答案 1 :(得分:1)

我的想法是,它正在等待希望完成运行,按照手册页:

  

如果channelId是阻止通道   命令管道然后关闭等待   为子进程完成。

由于wish进入无限循环(事件循环)并且永不退出,因此close命令将挂起。沿着同样的路线,[package require Tk](我相信)启动事件循环,因此会导致相同的行为。

我承认,虽然它正在加载.tclshrc,因为

  

如果在用户的主目录中存在文件.tclshrc(或Windows平台上的tclshrc.tcl),则交互式tclsh会在从标准输入读取第一个命令之前将该文件评估为Tcl脚本。

对我来说,[open“| tclsh”w]在交互式shell中结束似乎很奇怪。

作为旁注,[pacakge require Tk]在.tclshrc中看起来真的很奇怪。理论上,在运行Tcl(即仅命令行应用程序)时,您不会总是想要Tk(窗口和事件循环)......而且,当您确实需要它时,您就知道了。我想,对于他们自己来说,这对我来说似乎很奇怪。