2012-03-29 8 views
5

私は、Tclを組み込んだ小さなシェルアプリケーションを用意して、Tclコードの一部を実行しています。 Tclインタプリタは、Tcl_CreateInterpを使用して初期化されます。すべてが非常に簡単です:組み込みTclランタイムによって実行されるハンドル終了コマンド

  1. ユーザーがTclコマンドコマンドは、評価のためTcl_Evalに渡される
  2. 繰り返し

しかし有効なTclのあるユーザーが「終了」、もしTclインタプリタとシェルアプリケーションはすべて自動的に終了します。

Q:Tclインタープリタからのこの出口信号を捕まえることができる方法はありますか?私は本当にすべてのユーザーコマンドをチェックしたくないです。私はTcl_CreateExitHandlerを試しましたが、動作しませんでした。

ありがとうございます。

+1

* Tclの標準化されたライブラリ[その名前でよく知られている](http://tcllib.sourceforge.net/)のため、 "tcllib"のタイトルが修正され、参照が削除されました。あなたが実際に参照しているように見えるのは、あなたのプログラムにTclランタイムを埋め込むことです。 – kostix

+0

'Tcl_CreateExitHandler'は、終了をトラップし、さもなければ慌ただしくぶら下がるリソース(例えば、データベース接続)を解放するためのものです。それは起こってからの出口を止めることはできません。 –

+0

これは実際に私がやりたいことです - 終了時にリソースを解放してください。この場合、なぜ 'Tcl_CreateExitHandler'は動作しませんか? – ilya1725

答えて

0

Tcl_CreateExitHandlerを使用すると問題なく動作します。問題は、ハンドラの実装にprintfを追加し、出力が端末に表示されなかったことです。だから私はそれが呼ばれていないと思った。ただし、このハンドラが実行されるまでには、stdoutは存在しません。アプリケーション上でstraceを実行すると、ハンドラが正常に実行されていることが示されます。

この問題のもう1つの解決策は、atexitを使用してそこで終了イベントを処理することです。

8

コマンドを取り除く

rename exit "" 

またはユーザーをできるように、それを再定義し、それが無効であることを知っている:また

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

検討する価値はsafe interpではなく、メインにユーザーのコードが実行されていますシェル。そうすることで、ユーザーがアクセスできるものを正確に制御することができます。

また、interp(非安全)の子を作成し、そのinterpの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] 
    } 
} 

この方法:

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

それは働くことができます。しかし、私はまだ '出口'の呼び出しを保存したいと思います。 – ilya1725

+4

出口を利用できるようにしたいが、ユーザーには利用できないようにするには、安全なinterpルートをお勧めします。 – RHSeeger

+2

+1安全なinterpはほぼ確実に行く方法です –

1

exitコマンドの名前を変更しますユーザータイプがexitの場合は、カスタムexitコマンドを実行して、好きなことをすることができます。

+0

ありがとう、ハイ。しかし、これは私の問題を解決しません。もし 'exit'がTclから呼び出されたなら私のCアプリケーション全体は無条件に閉じます。私はまだ出口でいくつかのリソースをきれいにする必要があります。 – ilya1725

関連する問題