tcl8.6:stdlib中的'atexit()'或bash中的'trap“ ...” EXIT'的内置等效项是什么?

问题描述 投票:3回答:2

我正在寻找一个内置或标准软件包,该软件包提供的功能与stdlib的atexit()和bash的trap "..." EXIT类似或等同。

由于任何结束执行的程序方式,它都应终止,包括以下所有内容:

  • 自然到达脚本执行的结尾
  • 明确调用exit
  • 未捕获的error
tcl exit atexit tclsh
2个回答
3
投票

大多数情况下,拦截此类终止所需要做的就是拦截exit命令。

rename exit real_exit
proc exit args {
    puts "EXITING"; flush stdout; # Flush because I'm paranoid...
    tailcall real_exit {*}$args
}

如果您显式调用它,显然很有效,但是如果您只是放下脚本的末尾,在交互式会话中发信号通知文件的末尾,或者如果您的脚本稍后有错误并以错误消息。这是因为Tcl C API调用Tcl_Exit()通过调用exit起作用,并且如果没有退出进程,则直接退出自身。

小心退出脚本BTW;其中的错误比正常情况更难调试。


在这种情况下不起作用?主要是在解释器本身无法执行命令的地方(可能是因为它已经从自身下面删除了)或某些信号关闭了解释器(例如,由于各种原因默认未处理SIGINT)。


0
投票

基于@Donal的答案或多或少完整atexit

proc atexit { procbody } {
    if { [catch {set oldbody [info body exit]}] } {
        rename exit builtin_exit
        set oldbody { builtin_exit $returnCode }
    }
    proc exit { {returnCode 0} } [subst -nocommands {
        apply [list [list {returnCode 0}] [list $procbody]] \$returnCode
        tailcall apply [list [list {returnCode 0}] [list $oldbody]] \$returnCode
    }]
}

atexit-test.tcl的示例代码:

#!/usr/bin/tclsh8.6

source atexit.tcl

atexit {
    puts "EXITING($returnCode)"; flush stdout; # Flush because I'm paranoid...
}

atexit {
    puts "done($returnCode)..."; flush stdout; # Flush because I'm paranoid...
}

atexit {
    puts "almost($returnCode)..."; flush stdout; # Flush because I'm paranoid...
}

{*}$argv

...和终端会话:

$ ./atexit-test.tcl exit
almost(0)...
done(0)...
EXITING(0)
$ echo $?
0
$ ./atexit-test.tcl exit 5
almost(5)...
done(5)...
EXITING(5)
$ echo $?
5
$ ./atexit-test.tcl error "unhandled exception"
unhandled exception
    while executing
"{*}$argv"
    (file "./atexit-test.tcl" line 17)
almost(1)...
done(1)...
EXITING(1)
$ echo $?
1
$ 
© www.soinside.com 2019 - 2024. All rights reserved.