2012-03-29 73 views
5

我有一个嵌入Tcl以执行一些Tcl代码的小型shell应用程序。 Tcl解释器使用Tcl_CreateInterp进行初始化。一切都非常简单:由嵌入式Tcl运行时执行的句柄退出命令

  1. 用户类型Tcl命令
  2. 命令被传递给Tcl_Eval评估
  3. 重复

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

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

非常感谢。

+1

修正了标题并删除了对“tcllib”的引用,因为* Tcl [标准库]通常被该名称所知(http://tcllib.sourceforge.net/)。你似乎真正指的是将Tcl运行时嵌入到你的程序中。 – kostix 2012-03-29 08:08:09

+0

'Tcl_CreateExitHandler'用于捕获退出并释放资源(例如数据库连接),否则这些资源会很快地出现。它无法阻止退出的发生。 – 2012-03-29 14:41:13

+0

这实际上正是我想要做的 - 在退出时释放资源。为什么在这种情况下'Tcl_CreateExitHandler'不起作用? – ilya1725 2012-03-29 18:05:22

回答

0

使用Tcl_CreateExitHandler工作正常。问题在于我在处理程序实现中添加了printf,并且输出未显示在终端上。所以我认为它没有被调用。但是,在执行该处理程序时,不再有stdout。在应用程序上运行strace显示处理程序正在正常执行。

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

8

摆脱命令

rename exit "" 

,或者重新定义它让用户知道这是禁用:

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

也是值得考虑的运行用户在safe interp代码,而不是在主贝壳。这样做可以让您精确控制用户访问的内容。

您可能也可以创建一个子interp(非安全),只是禁用该interp的退出命令。

最后,你可以只重命名退出到别的东西,如果你只是想避免用户错误地键入它:

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

这可以工作。但我仍然想保留'退出'电话。 – ilya1725 2012-03-29 01:50:41

+4

如果你想让出口给你,但不给用户,我会推荐安全的interp路由。 – RHSeeger 2012-03-29 02:35:24

+2

+1安全interp几乎肯定是要走的路 – 2012-03-29 13:21:53

1

重命名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时,他/她将执行您的自定义退出命令,您可以在其中执行任何您喜欢的操作。

+0

谢谢,海。但是,这仍然不能解决我的问题 - 如果从Tcl调用exit,我的整个C应用程序将无条件关闭。我仍然需要在退出时清理一些资源。 – ilya1725 2012-03-29 18:53:17