尝试关闭 TCL 管道时 TCL 挂起

发布于 2024-09-18 09:36:46 字数 641 浏览 3 评论 0原文

启动 tclsh 并输入以下内容时:

close [open "|tclsh" w]

它工作正常。

但是,当在 ~/.tclshrc 中你有 package require Tk 时,同一行使 tclsh 挂起!

所有 GUI 软件包(如 Tk、Itk、Img、Iwidgets)都存在同样的问题,但是对于非 GUI 软件包(如 Itcl),它可以正常工作。

我该如何解决这个问题?重点是在 中使用 package require Tk 键入 close [open "|tclsh" w] 时,使 tclsh 不会挂起~/.tclshrc

wish 也存在同样的问题。 close [open "|wish" w] 使愿望挂起(使用空的 ~/.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。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

指尖凝香 2024-09-25 09:36:46

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

这假设每一行都是完整的可执行命令;当然,这可能不是真的,但是编写代码以使用 infocomplete 来组成行不太清楚,而且可能没有必要。 (你比我更清楚你实际上发送的是什么......)

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…)

╰沐子 2024-09-25 09:36:46

我的想法是,它正在等待愿望完成运行,根据手册页:

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

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

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

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

对我来说,[open "|tclsh" w] 最终出现在交互式 shell 中似乎很奇怪。

附带说明一下,[pacakge require Tk] 在 .tclshrc 中似乎是一件非常奇怪的事情。理论上,在运行 Tcl(即仅命令行应用程序)时,您并不总是需要 Tk(窗口和事件循环)...并且,当您确实需要它时,您知道您需要它。我想,对于每个人来说,这对我来说似乎很奇怪。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文