コンテキストの終了
様々なTruffle(ゲスト)言語では、終了のために異なるメカニズムが使用されることがあります。Truffle言語には、別の言語によってトリガーされた終了を検出して処理する方法がないため、これは最適ではありません。
Truffle 22.0では、ゲスト言語がTruffleContext.closeExited(Node,int)を使用してトリガーした、ポリグロット・コンテキストの明示的なハード終了がサポートされます。これで、基礎となるポリグロット・コンテキストの終了を言語がトリガーするための統一された方法が提供されます。トリガーされると、初期化済のすべてのゲスト言語にTruffleLanguage.exitContext(C,ExitMode,int)を使用して最初に通知され、次にすべてのコンテキスト・スレッドが停止され、最後にコンテキストがクローズされます。明示的ハード終了は単に「ハード終了」と呼ばれます。
ハード終了は、Truffleの3つのタイプの終了のうちの1つです。次のタイプの終了があります。
- 前述の新しいハード終了
- ハード終了通知は、
ExitMode.HARD
をTruffleLanguage.exitContext(C,ExitMode,int)
の2番目のパラメータとして使用して実行されます。
- ハード終了通知は、
- 暗黙的「自然終了」
- 通常のコンテキスト・クローズ中に発生します。
- 新しく導入された終了通知は、自然終了でも実行されますが、自然終了通知後にスレッドは強制停止されません。このため、依然として実行中のコンテキスト・スレッドによって自然終了がブロックされることがあります。
- 自然終了通知は、
ExitMode.NATURAL
をTruffleLanguage.exitContext(C,ExitMode,int)
の2番目のパラメータとして使用して実行されます。
- 「ソフト終了」
- 明示的終了は、例外タイプ
ExceptionType.EXIT
のTruffle例外をスローすることによってトリガーされます。 - 例外は、他のスレッドでTruffleによって自動的にスローされることはありません。また、それだけで終了通知またはコンテキスト・クローズをトリガーすることはありません。
- ソフト終了後、コンテキストは完全に使用可能です。ソフト終了の後に自然終了またはハード終了を行うことができます。
- 明示的終了は、例外タイプ
完全性を保つため、ポリグロット・コンテキストは、Context.close(true)
、TruffleContext.closeCancelled(Node,String)
、またはTruffleContext.closeResourceExhausted(Node,String)
を使用して取り消すことでもクローズできます。取消し操作では、すべてのコンテキスト・スレッドがすぐに停止され、終了通知なしでコンテキストがクローズされます。
ソフト終了
ソフト終了は、例外タイプExceptionType.EXIT
(ソフト終了例外)のTruffle例外をスローすることによってトリガーされます。例外は、他のスレッドでTruffleによって自動的にスローされることはありません。また、それだけで終了通知またはコンテキスト・クローズをトリガーすることはありません。言語がソフト終了例外を捕捉できなかった場合でも、最終的にソフト例外によって、埋込み側スレッドがPolyglotException
をホストにスローします。これには、PolyglotException.isExit() == true
とPolyglotException.getExitStatus()
(ソフト終了例外に指定された値と等価)が含まれます。
ソフト終了後、コンテキストは完全に使用可能です。ただし、埋込み側は、PolyglotException.isExit() == true
のPolyglotException
を確認したときにコンテキストをクローズする必要があります。この場合、ソフト終了の後に自然終了が続くためです。
自然終了
自然終了は、Context.close()
またはTruffleContext.close()
によってトリガーされる通常のコンテキスト・クローズ中に発生します。上の図に示す自然終了は、次のステップで構成されています:
-
自然終了は、
Context.close()
またはTruffleContext.close()
によってトリガーされます。 - 初期化済のすべての言語に対して終了通知が実行されます -
TruffleLanguage.exitContext(C,ExitMode,int)
(ExitMode.NATURAL
がExitMode
パラメータとして使用されます)。- ゲスト・コードは、終了通知中に正常に実行されます。
- 初期化されたすべての言語がファイナライズされます。
TruffleLanguage.finalizeContext(C)
が、すべての初期化済言語に対してコールされます。- ゲスト・コードは、ファイナライズ中に正常に実行されます。
- すべての言語が破棄されます。
TruffleLanguage.disposeContext(C)
が、すべての言語に対してコールされます。
ハード終了
この項では、ハード終了のプロセスについて詳しく説明します。ポリグロット・コンテキストのハード終了は、Context.Builder.useSystemExit(boolean)
を使用してカスタマイズできます。このため、次の説明はさらに2つの項に分かれています。1つはシステム終了が有効になっていないケース(Context.Builder.useSystemExit(false)
- デフォルト)、もう1つはシステム終了が有効になっているケース(Context.Builder#useSystemExit(true)
)に対応しています。終了プロセスの図は、上の図に示されています。また、この図では、終了プロセスがコンテキスト取消しプロセスに関連付けられています。いくつかの枠が赤色になっているのは、その時点でコンテキストが無効であり、ゲスト・コードを実行できないことを示します。詳しく説明すると、最初のTruffleセーフポイントが、ハード終了操作または取消し操作のどちらが進行中かに応じて、特別なThreadDeath
終了例外または特別なThreadDeath
取消し例外をスローします。
useSystemExitが無効な場合の動作(デフォルト)
-
終了はTruffleContext.closeExited(Node,int)によってトリガーされます。
- 初期化済のすべての言語に対して終了通知が実行されます - TruffleLanguage.exitContext(C,ExitMode,int) (
ExitMode.HARD
がExitMode
パラメータとして使用されます)。- ゲスト・コードは、終了通知中に正常に実行されます。
- コンテキストが終了通知(ステップ2a)の間に取り消されずに、ステップ2bまで進んだ場合、終了プロセスが次のステップに進みます。それ以外の場合、終了通知は中断され、コンテキストがただちに取り消されます。
- すべてのコンテキスト・スレッドは、特別な
ThreadDeath
終了例外をTruffleセーフポイントからスローして、強制的に停止されます。- スレッドを確実に終了するには、
ThreadDeath
が常にすぐ再スローされること、ゲスト言語の例外ハンドラが実行されないこと、また最終的にブロックが実行されないことが、言語によって保証される必要があります。 - 最終的に埋込み側スレッドが
PolyglotException
をスローします。これには、PolyglotException.isExit() == true
と、PolyglotException.getExitStatus()
(最初のTruffleContext.closeExited(Node,int)
へのコールの2番目のパラメータに指定された終了コードと等価)が含まれます。 - 図に示すように、ステップ3以降の終了プロセスは取消しプロセスと似ています。ただし、取消しプロセスでは特別な
ThreadDeath
取消し例外が使用され、ホストにスローされるPolyglotException
にPolyglotException.isExit() == true
ではなくPolyglotException.isCancelled() == true
が含まれます。
- スレッドを確実に終了するには、
- 初期化されたすべての言語がファイナライズされます。
TruffleLanguage.finalizeContext(C)
が、すべての初期化済言語に対してコールされます。TruffleLanguage.finalizeContext(C)
でゲスト・コードを実行すると、特別なThreadDeath
終了例外が最初のTruffleセーフポイントからスローされます。- 言語は、ゲスト・コードの実行が必要となるファイナライズをスキップする必要があります。言語がゲスト・コードを
TruffleLanguage.finalizeContext(C)
で実行できるかどうかは、TruffleLanguage.exitContext(C,ExitMode,int)
が前にExitMode.NATURALを使用してコールされたかどうかを確認するか、TruffleContext.isClosed()
によってfalse
が返されるかを確認することで調べられます。
- すべての言語が破棄されます。
TruffleLanguage.disposeContext(C)
が、すべての言語に対してコールされます。
- コンテキストがクローズされます。
useSystemExitが有効な場合の動作
- 終了はTruffleContext.closeExited(Node,int)によってトリガーされます。
- システム終了が無効な場合と同じ。
- 初期化済のすべての言語に対して終了通知が実行されます - TruffleLanguage.exitContext(C,ExitMode,int) (
ExitMode.HARD
がExitMode
パラメータとして使用されます)。- システム終了が無効な場合と同じ。
System.exit(int)
がコールされ、ホスト・アプリケーション全体を終了し、できるかぎり早く終了できるようにします。System.exit(int)
に渡される終了コードは、TruffleContext.closeExited(Node,int)
への最初のコールに2番目のパラメータとして指定された終了コードです。
使用例
SimpleLanguageでは、ハード・コンテキスト終了の使用方法について説明されます。次の内容について説明されます。
- SLExitBuiltinでは、コンテキスト終了のトリガーについて説明します。
- SLRegisterShutdownHookBuiltinでは、SLLanguageで定義される終了通知中に実行されるシャットダウン・フックの登録について説明します。
- SLExitTestでは、前述の定義されたビルトインの使用方法について説明します。