当管道有信息时,不调用可读过程

Readable procedure not getting called when pipe has info

提问人:Active Hub 提问时间:8/5/2023 更新时间:8/7/2023 访问量:42

问:

在 linux 上,我使用“mkfifo pip”创建了一个管道文件。在一个终端上,我发出“tail -f pip”,在另一个终端上,我发出“ls > pip”。我可以看到从第二个终端到第一个终端的信息流。

我创建了一个 TCL 脚本来读取流入点的信息。

fconfigure stdout -buffering none
set fd [open "pip"]
fconfigure $fd -blocking 0 -buffering line
fileevent $fd readable [list Treading $fd]

proc Treading {desc} {
        gets $desc line
        puts stdout "Got line - $line"
}

while {1} {
        puts "waiting..."
        after 2000
}

我运行了该程序并从另一个终端发出“cat > pip”,在输出中我没有看到任何从 Treading 过程调用的“Got line”打印。

$tclsh sockpip.tcl 
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...

如果我遗漏了什么,有人可以帮我澄清一下吗?我想让事件驱动的编程工作。

提前致谢。 紫外线。

Linux 文件 管道 TCL 事件驱动

评论

0赞 Active Hub 8/11/2023
感谢您的回复。但我的要求是,在我创建fileevent之后,我应该继续做一些其他任务(我认为使用“after”是我的坏主意)。当文件中发生某些更改时,应发生 file事件。有人可以帮助满足此要求吗?

答:

2赞 Colin Macleod 8/5/2023 #1

要触发事件,您需要使用非阻塞形式 ,请参阅 https://www.tcl-lang.org/man/tcl8.6/TclCmd/after.htm#M6,并且需要启动 Tcl 事件循环。而不是:readableafter

while {1} {
        puts "waiting..."
        after 2000
}

尝试:

proc waiting {} {
        puts "waiting..."
        after 2000 waiting
}

waiting
vwait forever
2赞 Donal Fellows 8/7/2023 #2

关键问题是你正在使用一个阻塞。Tcl 解释器是严格的单线程解释器,并且仅在您调用 or(或在 Tcl 的 C API 中包装这些或调用的其他东西)时才提供事件循环。不建议以递归方式调用它们,因为您可能会因可重入回调而陷入混乱,而您不希望这样aftervwaitupdateTcl_DoOneEvent()

但是,您可以使用协程和非阻塞来执行循环,如下所示:after

proc snooze {delay} {
    after $delay [info coroutine]
    yield
}

coroutine MyWaitLoop apply {{} {
    while {1} {
        puts "waiting..."
        snooze 2000
    }
}}

vwait forever;  # Run the event loop until you stop it

由于这是在事件循环中等待,因此将调用管道的处理程序。