【问题标题】:Handle exit command executed by embedded Tcl runtime处理嵌入式 Tcl 运行时执行的退出命令
【发布时间】:2012-03-29 00:02:32
【问题描述】:

我有一个嵌入Tcl 的小型shell 应用程序来执行一些Tcl 代码。 Tcl 解释器使用 Tcl_CreateInterp 初始化。一切都很简单:

  1. 用户键入 Tcl 命令
  2. 命令被传递给 Tcl_Eval 进行评估
  3. 重复

但是如果用户键入“exit”,这是一个有效的 Tcl 命令,整个事情 - Tcl 解释器和我的 shell 应用程序 - 会自动退出。

问:有什么方法可以捕捉到来自 Tcl 解释器的退出信号。我真的不想检查每个用户命令。我试过Tcl_CreateExitHandler,但没用。

非常感谢。

【问题讨论】:

  • 修复了标题并删除了对“tcllib”的引用,因为这是一个标准化的库for Tcl is commonly known by that name。您似乎真正指的是将 Tcl 运行时嵌入到您的程序中。
  • Tcl_CreateExitHandler 用于捕获出口并释放资源(例如,数据库连接),否则会令人讨厌。它不能阻止退出的发生。
  • 这实际上正是我想要做的——在退出时释放资源。为什么Tcl_CreateExitHandler 在这种情况下不起作用?

标签: tcl interpreter


【解决方案1】:

摆脱命令

rename exit ""

或者重新定义它让用户知道它被禁用了:

proc exit {args} { error "The exit command is not available in this context" }

另外值得考虑的是在safe interp 中而不是在主shell 中运行用户的代码。这样做可以让您准确控制用户可以访问的内容。

您也可以创建一个子 interp(非安全)并禁用该 interp 的 exit 命令。

最后,如果您只是想避免用户输入错误,您可以将 exit 重命名为其他名称:

namespace eval ::hidden {}
rename exit ::hidden::exit

【讨论】:

  • 可以的。但我仍然想保留“退出”电话。
  • 如果您希望退出对您可用,但对用户不可用,我建议您使用安全的 interp 路线。
  • @jk。总的来说,我同意这一点。明显的警告是,他可能希望允许用户使用 Tcl shell 的全部功能,但不希望他们意外退出程序。从这个问题很难判断这是否属实。
  • 是的,最后一条评论:我不想限制用户可以输入的内容。有什么方法可以在自定义退出程序中发送 ctrl+D 信号?
  • 自定义退出过程中为什么要发送ctrl+D?如果您将退出命令“移开”(通过重命名),您仍然可以调用它。
【解决方案2】:

重命名exit 命令:

rename exit __exit

proc exit {args} {
    puts -nonewline "Do you really want to exit? (y/n) "
    flush stdout
    gets stdin answer
    if {$answer == "y"} {
        __exit [lindex $args 0]
    }
}

这样,当用户输入exit时,他/她就会执行你自定义的退出命令,你可以在其中做任何你想做的事情。

【讨论】:

  • 谢谢,海。但是,这仍然不能解决我的问题 - 如果从 Tcl 调用 exit,我的整个 C 应用程序将无条件关闭。我仍然需要在退出时清理一些资源。
【解决方案3】:

使用Tcl_CreateExitHandler 可以正常工作。问题是我在处理程序实现中添加了一个printf,并且输出没有显示在终端上。所以我认为它没有被调用。然而,当这个处理程序被执行时,已经没有stdout了。在应用程序上运行strace 表明处理程序正在正常执行。

这个问题的另一个解决方案是使用atexit 并在那里处理退出事件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多