【问题标题】:TCL spurious hang on exitTCL 虚假挂起退出
【发布时间】:2015-09-02 11:05:53
【问题描述】:

简单的TCL挂机

我使用非常简单的 TCL 脚本来重现我的问题。我在带有 activeTCL 8.6.4.1 的 Windows 7 上运行。 我使用一个简单的批处理文件 (loop.bat),它在循环中调用一个 tcl 脚本 (1.tcl)。然后该脚本执行一些“放置”并打开另一个 TCL shell 以调用另一个 TCL 脚本 (2.tcl)。第二个脚本执行两次“放置”,一次在 stdout 上,一次在 stderr 上,然后返回。

为了重现该问题,我启动了 16 个 loop.bat 实例并让它运行了一整夜。当我早上回来时,大约有一半的实例被停止(挂起)。

这是我使用的代码:

循环.bat

@echo off
:loop
tclsh86 1.tcl
goto loop

1.tcl

puts "start 1.tcl"
set error [catch {eval {exec tclsh86 2.tcl >@stdout 2>@stderr}} results]
puts "error = $error"
puts "results = $results"
puts "end 1.tcl"
return 0

2.tcl

puts stdout "Print to stdout from 2.tcl."
puts stderr "Print to stderr from 2.tcl."
return 1

【问题讨论】:

  • 如果你使用exit而不是return会发生这种情况吗?
  • @DonalFellows :是的,我在退出时遇到了完全相同的问题,但我读到它的代码没有遵循一些 MSDN 指南,并且可能会导致我遇到的挂起。这就是为什么我切换到级联返回而不是退出,但我仍然看到它。
  • eval{...} 部分看起来像是一个额外的步骤。打开它,所以它只是[catch {exec ...} resuts]
  • @wolfhammer 你是完全正确的。评估是从我的“真实案例”中剩下来的。我删除了它以了解它是否以任何方式与我的问题相关联,但我仍然像以前一样挂起。

标签: tcl exec stdout freeze stderr


【解决方案1】:

为了重现该问题,我启动了 16 个 loop.bat 实例并让它运行了一整夜。当我早上回来时,大约有一半的实例被停止(挂起)。

使用“exec”、“puts”地址和批处理循环的迭代创建了新的线程和文件套接字。如果创建套接字或线程的速度快于恢复速度,则调用的“子”进程最终将耗尽可用的套接字或线程。

这可能有助于解释:https://web.archive.org/web/20190217153445/https://blogs.msdn.microsoft.com/oldnewthing/20050729-14/?p=34773

【讨论】:

  • 我看不出链接是如何相关的。它讨论了一个进程的线程堆栈大小。但是在这个问题中产生了新的进程,每个进程都有自己的堆栈空间。显然是某些原因导致了问题,但我认为 R Chen 的博客文章没有解释它。或者我需要更多解释,因为我没有看到。
【解决方案2】:

解决方案可能是让 Windows 更多地控制进程并使用start 执行tclsh86

@echo off
:loop
start /b /wait tclsh86 1.tcl
goto loop

这可能会解决问题。 '/b' 禁止在每次启动 tclsh86 时创建新控制台。

【讨论】:

    猜你喜欢
    • 2012-03-16
    • 2018-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多